# Welcome

[Balena](https://balena.io/) makes it easy to deploy code to fleets of connected devices, bringing the power of Linux containers to the edge. We've optimized the cloud paradigm for remote devices, taking familiar container workflows and custom building for low overhead, high reliability, and out-of-the-box support across a wide variety of devices. With a few simple commands, you can monitor, manage, and update your fleet from anywhere.

Our [balena primer](/learn/introduction/primer) covers the platform from end to end, walking through all the pieces and how they fit together.

Ready to dive in? The [getting started guides](/learn/getting-started) take you step-by-step through creating your first fleet, provisioning your first device and deploying your first release.

Once you're up on the basics, we've got all the info you need to build and manage larger fleets with more advanced functionality:

### [Develop](/learn/develop)

As you develop your application and grow your fleet, these guides will help you configure and package your services, ensuring you have the proper container setup and that you can interact with hardware and system resources.

### [Deploy](/learn/deploy)

When you're ready to bring your application from one device to an entire fleet, read up on the basics of the balena build pipeline, as well as some advanced features to make your code deploys smaller, faster, and more reliable.

### [Manage](/learn/manage)

Check here for details on all the tools we provide for managing your device fleet, including configuration, variables, SSH access, and checking device logs all from the dashboard.

### [Masterclasses](/learn/more/masterclasses) & [balenaHub](https://hub.balena.io/)

To gain mastery in various products and workflows supported by balena, head on over to [balena Masterclasses](/learn/more/masterclasses) and checkout out projects made by the community on [balenaHub](https://hub.balena.io/).

Haven't found what you're looking for? Stop by our [FAQ](/faq/questions) and [Reference](/reference/hardware) sections, or better yet, use the search in the upper-left corner. And if you still have questions, [help](/learn/accounts/support-access) is always available! Refer to the balena Glossary for definition on any of the terms referred in the docs.

Check out our [Feature Requests Page](https://forums.balena.io/c/feature-requests/96) to share your ideas and upvote the things that matter most to you.


# Introduction


# Core Concepts: A balena primer

The balena platform encompasses device, server, and client software, all designed to get your code securely deployed to a fleet of devices. The broad strokes are easy to grasp: once your device is set up with our [host OS](/reference/os/overview), you can push code to the balena [build servers](/learn/deploy/deployment#the-balenacloud-build-server), where it will be packaged into containers and delivered to your fleet. All your devices and their services can be managed, monitored, and updated from your [balena dashboard](https://dashboard.balena-cloud.com/).

If you're eager to learn more about the inner workings, you're in luck! This guide covers the components and workflows involved in a typical balena deployment, with enough detail to answer the most common questions. If you're ready to dig in deeper, why not [get started](/learn/getting-started) with a project of your own?

Refer to the [balena Glossary](/learn/more/glossary) for definition on any of the terms referred in the docs.

## On your device

<figure><img src="/files/ESSEsnyO1wiwqQQC5Kkf" alt=""><figcaption></figcaption></figure>

Devices in the balena ecosystem run [balenaOS](https://www.balena.io/os), a bare-bones, [Yocto Linux](https://www.yoctoproject.org/) based host OS, which comes packaged with [balenaEngine](https://www.balena.io/engine), our lightweight, [Docker](https://www.docker.com/)-compatible container engine. The host OS is responsible for kicking off the device supervisor, balena's agent on your device, as well as your containerized services. Within each service's container you can specify a base OS, which can come from any existing Docker base image that is compatible with your device architecture. The base OS shares a kernel with the host OS, but otherwise works independently. If you choose, your containers [can be configured](/learn/develop/multicontainer) to run as privileged, access hardware directly, and even inject modules into the kernel. The balena device supervisor runs in its own container, which allows the device to continue running and pulling new code even if your application crashes.

### Host and kernel updates

Balena is built with the goal of 100% updatability. While the balena device supervisor and your application containers are easy to update without losing connection to the device, the [process for updating](/reference/os/updates/update-process) the host OS involves a few more steps. To mitigate problems while updating, balena creates an additional partition of identical size to the boot partition. The supervisor downloads a new OS version and boots the device from the alternative boot partition. This way, we can ensure that the new version of the OS is downloaded and installed correctly before rebooting the device to the new version. Even if the new version fails to boot for some reason, our system is built in such a way that the next boot will bring the device back to the original working version of the host OS, operating and ready to download a correctly installed new version.

It is important to note that all balena devices, both those in production and development today, have the ability to have their host OS updated. For most devices, this can even be done directly [through the dashboard](/reference/os/updates/self-service).

### Device provisioning

So how are devices added to your balena fleets? A key feature of balena is that a provisioning key for your fleet is embedded in the balenaOS image download. When the device boots up for the first time, it uses the provisioning API to register itself with balena. A new device entry on the balena backend is created, and a device API key for this device is generated. Once the provisioning is successful, the provisioning API key is deleted from the device. Unless someone downloads the OS from your dashboard (or via the CLI), a device cannot enter your fleet. While the details of provisioning differ depending on the device type (does it have an SD card slot? Does it boot from on-board flash?), the following things always happen at first boot:

First, the device connects to the network and performs its early provisioning, which registers it on your dashboard. Then, the container partition is decompressed, and the device supervisor starts. This is the part that takes the most time. As soon as the supervisor starts, it registers onto cloudlink and receives its unique balena API key. At that point, you will see the device as online in your dashboard and can use the device as normal. If the fleet that the device joins already has releases, the new device downloads the latest one and begins operating.

## Code deployment

`balena push` is the recommended method for deployment and [development](/learn/develop/local-mode) on the balenaCloud platform. To use `balena push` you need to first [install the balena CLI](/reference/balena-cli/latest#installation) and ensure you are logged in to your account with `balena login`.

<figure><img src="/files/OtNIq71bUlccSvAWq5ge" alt=""><figcaption></figcaption></figure>

### Building containers

When you run the `balena push <APP_NAME>` command from your development machine it will essentially take your project (or repository) folder, compress it and send it to the [balenaCloud build server](/learn/deploy/deployment#the-balenacloud-build-server) where it will be built. Your code is built in an environment that matches the devices in your fleet. So if you’re pushing an app for BeagleBone Black devices, we’ll build your code in an ARMv7 environment. For Raspberry Pi 1, it's ARMv6. In fact, we provide native ARM builders for ARM images, just as we use x86 servers to build images for x86 devices.

For releases with [multiple containers](/learn/develop/multicontainer), a `docker-compose.yml` file will need to be included at the root of your project. This configuration file specifies the services that make up your release, as well as the system resources each service has access to. Releases with a single container will have a default `docker-compose.yml` file generated if none is included.

Most services will need to include a [Dockerfile](/learn/develop/dockerfile), which contains a list of commands for the builders. For each service, the builders will pull a base OS, install packages and dependencies, clone git repositories, and run any other steps you define for the setup and initialization of that service.

For Node.js services, you can use a package.json file without a Dockerfile. In this case, the builders create an implicit Dockerfile, which simulates the build process a Node.js/npm project expects. In this way, we are able to transparently run Node.js services on balena, while also taking advantage of some of Docker’s caching features. A Dockerfile will always give you more power to fine-tune, but you can start fast without and shift to a Dockerfile whenever you like.

### Getting to the devices

Once your Docker images are built, they are stored in our container registry, and the balena device supervisor is alerted that a new version of your application is ready. If a device is offline at the time, it will be made aware of the new containers when it comes back online. The communication between balena and your device is encrypted at all times, either through HTTPS or a VPN that we set up for the devices in your fleet.

The device supervisor, using [delta updates](/learn/deploy/delta), then downloads the binary differences between the old and the new images, stops the old services, and starts the new ones. You can control the exact sequence by configuring the supervisor to use [different update strategies](/learn/deploy/release-strategy/update-strategies). The services themselves can also make use of [update locking](/learn/deploy/release-strategy/update-locking) to block updates from happening during critical times (e.g. [a drone that is flying](https://www.youtube.com/watch?time_continue=1569\&v=75vm6rRb6K0), or an industrial machine that is in the middle of an operation).

As the downloads proceed, you can watch the progress in the balena dashboard. You can click on any device to see more detailed information about the services being downloaded:

<figure><img src="/files/5gsxGjNHmmy2x8D918xK" alt=""><figcaption></figcaption></figure>

## Device management

Once your services are up and running, you can use the dashboard to monitor and interact with them. Messages from the device supervisor, as well as anything written by your services to `stdout` and `stderr`, will appear in the *Logs* window, which can be filtered by service. Our built-in [web terminal](/learn/manage/ssh-access) allows you to SSH into any running services, as well as the underlying host OS.

Much of the device, service, and fleet information provided by the dashboard is managed through the [balena API](/reference/api), and can also be viewed and modified using the [CLI](/reference/balena-cli/latest) or the [Node.js](/reference/sdk/node-sdk/latest) and [Python](/reference/sdk/python-sdk/latest) SDKs. Balena has been designed so users can build rich experiences, combining device-level data provided by balena with higher-level fleet-specific data that lives in other data domains.


# Going to production

Deploying a fleet of remote, connected devices requires some careful planning. A proper solution needs to take into account where the devices will be deployed, what the devices need to do, how the devices will be maintained, and of course, the available budget. To help you get started we've outlined a basic project plan, covering recommended steps for preparing a production fleet as well as the questions you'll want to consider along the way.

## Phase 1: Design

The first step in designing a solution is to determine how and where your devices will run. Your use case will drive the selection of the *hardware* and the *operating environment* required to successfully deploy your application.

### Hardware

There are a number of single-board computers capable of supporting Linux and running applications on the edge. The options vary widely in terms of capability and price, so it's important to pay close attention to the features that will meet your application's needs. Regardless of the hardware platform you choose, you'll want to consider the following:

* CPU: Do you have software components that require the x86 architecture? ARM chips are often cheaper and consume less power, but x86 can often provide more processing capability.
* RAM: You should ensure that you have a comfortable buffer of memory. Software must be able to evolve with changing business needs and you may find yourself deploying new features beyond what you originally scoped. Having plenty of available memory will save you time and effort (and possibly an expensive upgrade cycle) later.
* Peripherals: Are there special hardware devices that will need custom drivers?
* Storage: SD cards are common in embedded devices, but are slower and *much* less reliable than onboard flash storage. Especially if your application will be performing many read/write cycles, avoiding SD storage will reduce the risk of data corruption. If using SD cards, we recommend SanDisk Extreme Pro SD cards.
* Power: Not all power supplies are fully compatible with all boards (especially USB-based supplies). It is important to confirm that the power supply is capable of actually providing the required power before widespread deployment. If using any peripherals, the power requirements will be higher than the board's rating.

Of course, the single biggest choice you have to make is whether to use off-the-shelf hardware or a custom device. An off-the-shelf device has many advantages, including lower price, faster availability, and broader industry support. But it's possible that no existing device fully meets your needs. In this case it's crucial to think about your operating environment—you need to be sure that it will work with your hardware and that it can be kept up to date with the latest security patches.

### Operating environment

One of the challenges in building applications for distributed fleets is aligning your development environment with the operating environment running on your devices. You'll need a way to make sure your application and its dependencies work with your device's architecture, as well as a plan for pushing updates to your fleet without losing access to your devices.

Balena solves for these concerns by running balenaOS, a bare-bones host OS with a lightweight, Docker-compatible container engine, [balenaEngine](https://www.balena.io/engine). With containers, you can develop your application in the way you are most comfortable, and then run that environment on your device without worrying about the underlying hardware support. Any dependencies, such as libraries and runtime environments, will already be packaged in the container.

Containers also make remote updates a straightforward process. A new release can be downloaded, verified, and started while the host OS maintains a network connection and handles any issues.

One thing to consider is whether you'll want to use one container or many. Each approach has its advantages. A single container is the simplest to manage—there's no inter-container communication or resource contention to worry about. But it does mean that you will need to manage all the components of your application in one place.

Using multiple containers allows you to separate components and even development teams. Splitting your application into containerized services could, for example, allow one team to work on the frontend of your application while another is working on the backend, with each team sending updates independently. The different teams could even use completely different operating environments: one team could use Debian and another Fedora. This does require some coordination, as you will need to assign the resources needed by each container via something like a [Docker Compose](https://docs.docker.com/compose/overview/) file.

## Phase 2: Prototype

During the prototyping phase, it's important to develop on the same device you'll be using in your production fleet. It may be tempting to use a virtual device, but there are a number of drawbacks to this approach. Virtual devices tend to be more difficult to work with than physical devices and are often much slower. By sticking with the same device through prototype, pilot, and production phases, you'll reduce the risk of any unexpected failures along the way.

You'll want to make sure you have easy access to your device, especially in the case that something goes wrong. It's best to prototype in a local lab under your control. At this stage of development, your application is incomplete and not fully tested, so you want a safe environment where you can quickly develop without risk of exposing data externally.

The prototyping phase is where some of the developer-focused features of balena start to come into play, offering a number of ways to access the host OS and containers running on your device:

### Development images

When developing a new application, you should consider using a [development image](/reference/os/overview) of balenaOS. These images have a number of features that, for security reasons, are not present in the production releases of balenaOS. These include:

* Passwordless SSH access to the host OS
* Access to the Docker socket
* Serial and console logging and interactive login
* Local mode functionality

### Local mode

BalenaOS [local mode](/learn/develop/local-mode) gives you the ability to build and deploy to a device on the local network without involving the balena cloud builder. This allows you to very quickly iterate and test functionality—in many cases, such as configuration changes or changes made to code in an interpreted language, updates can be deployed without requiring a build at all. A local deployment lets you directly mirror your development environment on a test device.

### Connectivity

While prototyping, you should start thinking about how your devices will be connected when deployed in the real world. If it's possible to have network settings preconfigured, or to have everything done by DHCP, this is easy. But most devices will need onsite configuration.

Balena provides the ability to configure networking from inside containers and exposes a great deal of functionality to make this easier. One example is the [wifi-connect](https://github.com/balena-os/wifi-connect) project, which allows the device to create its own WiFi access point that users can connect with to configure proper credentials. The balena [supervisor API](/reference/supervisor/supervisor-api#patch-v1-device-host-config) also makes it possible to configure more advanced networking parameters, including hostname and proxy configuration.

### Multiple developers

During the prototyping phase, you may want to allow multiple developers to share resources. With balena, you can add multiple developers as [collaborators](/learn/accounts/fleet-members) to a fleet, giving them the ability to manage the fleet's devices and push code updates.

## Phase 3: Pilot

After your application development is mostly complete, it's important to do some more real world testing. Balena exposes functionality to make this easy as well, providing tools that help you move from the prototype phase toward a full production environment:

### Production images

At this point it makes sense to move from development balenaOS images to full production images, ensuring that your application still runs properly without full local console access. You can still [access](/learn/manage/ssh-access) the host OS and containers via the balena dashboard and CLI, but the production balenaOS image will close all open inbound ports.

For Production and Enterprise plan users who require a stable, supported release, you should choose an [ESR version](/reference/os/extended-support-release) of the host OS. An ESR version guarantees that you will only have to update the host OS on the devices at most twice a year to ensure you are on a supported version. You can view devices that have ESR versions of the host OS [here](/reference/os/extended-support-release#supported-devices).

### Test outside the lab

Testing outside the lab helps you see how your device behaves in networks that are not fully under your control. Ideally, this should be done in an environment that mimics where your devices will be when they are in production, but is still at least somewhat accessible. For example, if you are building a consumer device, you could have your employees and their families test in their homes. You might also look for customers who are willing to be alpha testers, who might provide feedback about your application while understanding that it's not quite done yet.

### Log collection

It's crucial that you are able to get logs and telemetry from your devices once they're out of the lab. You can use the console logging functionality exposed in the balenaCloud dashboard to read your application logs.

If your application generates enough log data that you need an analytics platform to make sense of it all, consider [adding a log collection agent](https://balena.io/blog/how-to-create-a-custom-logging-system-for-longer-log-retention/) to your containers, just as you would in any other environment.

### Update testing

Make sure to test all the update functionality you can before your devices are out in the wild and inaccessible. For both release and host OS updates, balena includes a number of features to make sure the update process doesn't affect your ability to connect to your devices and restore functionality, but you'll still want to understand the factors that can affect the update process.

Specifically, think about testing:

* loss of power during an update
* loss of network during an update
* pushing a new update while another is in progress

Understanding how your devices handle adverse conditions allows you to be confident in your fleet's ability to receive timely updates.

## Phase 4: Production

Now that your testing is wrapping up, it's time to get your devices into a fleet out into the world! At this point you'll be moving from a primarily development-focused perspective to a primarily operations-focused perspective, at least for the current release of your application. Of course, you may want to continue development on the next version, knowing that you can safely roll out updates to your fleet at any point with balena!

### Preloading images and preregistering devices

While a device will provision itself and download your latest release as soon as it's turned on and connected to the Internet, this might not be the experience you want your users to have. It would be nice to have something that works right away, rather than having to wait for a potentially slow download to finish.

Happily, you can [preload](/reference/balena-cli/latest#preload) your release into a balenaOS image with a one-time process. Then, when that image is flashed onto your devices in the factory, it will have the release already installed and ready. Any updates made to the fleet after the preloading process will be downloaded and applied when the device is brought online, so there's no need to worry about devices that have been sitting in a warehouse or on store shelves.

For situations where you need to register your devices before they have been powered on or connected to the network, you can [preregister](/reference/balena-cli/latest#device-register) them. Preregistering a device allows the creation of individually registered devices in a fleet, which is extremely useful in situations such as manufacturing where a device may require tracking, as a specific device UUID can then be associated with a specific customer order.

More information about preloading images and preregistering devices can be found in the [CLI Advanced Masterclass](/learn/more/masterclasses/advanced-cli) or the [CLI documentation](/reference/balena-cli/latest).

### Canary deployments

When updating software on production devices, it makes sense to be cautious and start with a few devices to make sure nothing goes wrong. A common practice is to start with a few "canary" devices and then slowly roll the update out to larger and larger numbers of devices.

The balena API includes functionality that allows for [fine-grained control of updates](https://github.com/balenalabs/staged-releases). With these endpoints, you can turn off automatic release updates, set a target release for the whole fleet, or set target releases for a specific subset of devices. The [device tag](/learn/manage/filters-tags#device-tags) and [filter](/learn/manage/filters-tags#device-filters) functionality makes it easy to assign groups of devices to certain phases of your deployment.

## Further reading

For more information about common anti-patterns, see [Anti-patterns, or how to break your balenaOS devices](/learn/more/anti-patterns).


# Security

Balena takes your fleet’s security very seriously. We understand that your data and devices are valuable and often critical, and we take precautions to ensure that your devices and data are not compromised.

## Trust and Transparency

At balena, our approach to security is guided by ISO 27001:2022, ensuring a structured, reliable system that aligns with our values. Our ISMS (Information Security Management System) has undergone multiple audits by accredited third parties to verify our compliance and effectiveness.

Rather than using rigid templates, we customized our implementation to fit our team's way of working, maintaining transparency without compromising our culture. This system is continually monitored and improved, demonstrating our commitment to providing a secure and dependable platform while staying true to who we are.

For transparency we maintain a trust center at [trust.balena.io](https://trust.balena.io), where we surface our monitored information security controls, sub processors and security acknowledgements.

## Secure Ecosystem

Security begins with the ability to send timely updates to your devices. By providing a mechanism for regular, reliable, and verifiable updates, balena gives you the tools you need to keep your device fleet up to date and protected against attacks.

To keep the balena ecosystem secure, we focus on the principle of least privilege—permissions are given only as necessary, and no information is available to any account or device unless it is required for the tasks being performed. We take a number of steps to isolate all components in the update process, so that unauthorized access to any one component will not provide enough information to access additional components, accounts, or devices.

The core mechanism for implementing this security approach is through API access control. By controlling access to the API, the actions that are permitted, and the available communication channels, we can protect fleets at all points of entry.

In this document, we will further explain how the balena infrastructure implements access control across the entire lifecycle, from device access and runtime management, to the image build process, and finally to the API and backend services.

## Access to balena

The first points of access to the balena ecosystem are the user dashboard and the CLI. From these, a user can add and remove SSH keys, retrieve an API token, and manage devices. Multiple methods of authentication are supported for logging in:

* Simple username/password authentication is supported, though not recommended for production accounts.
* Balena supports a number of [OpenID Connect](https://openid.net/connect/) providers, including GitHub and Google.
* Two-factor authentication using the Time-based One-time Password Algorithm (TOTP) is fully supported. This enables integration with tools such as Google Authenticator.

## Device access

Device access is managed by our host operating system, [balenaOS](/reference/os/overview). BalenaOS is a thin Linux that supports the balena services and user containers. BalenaOS is built using [Yocto Linux](https://www.yoctoproject.org/), the de facto standard for building lightweight embedded Linux environments. Using Yocto allows balena to build images that contain no unused or unnecessary code in either userspace or the running kernel, minimizing the device's available attack surface. All balena software running on devices is 100% open source and can be independently audited and verified. Device access is granted to a subset of balena employees to enable support and device troubleshooting. This access is controlled by ssh key access and only after access is explicitly granted to balena.

User source code and images are stored on balena backend servers with access limited only to administrative/operational staff and are not exposed to anyone outside of balena. It is also possible to bypass the balena builder entirely and push only pre-built artifacts, meaning that balena never has access to the code at any point.

When a balenaOS image is downloaded and flashed to a device, it comes with a provisioning key that allows devices to join a specific fleet. When the device boots up for the first time, it uses the provisioning API to register itself with balena. A new device entry on the balena backend is created, and a device API key for this device is generated. Once the provisioning is successful, the provisioning API key is deleted from the device. The device API key allows control of the following:

* changing the device metadata
* reading metadata of the fleet associated with the device
* reading variables associated with the device
* reading variables for the fleet that is associated with the device
* reading build logs of the fleet associated with the device

If a device is compromised, the device API key can only be used to read information about the device or the fleet the device is associated with. A fleet owner can remove and revoke the API key of a compromised device by simply deleting the device from the dashboard.

A device API key also allows a device to request the latest release. When a device requests an update, this API key is sent to balena and authenticated. Once the API key has been authenticated, a Docker pull is initiated on the device.

Both the Docker pull request and the actual image download process are performed using HTTPS, so are TLS encrypted. HTTPS connections are always outbound from the device to the balena service, meaning that no inbound connections are created and no inbound ports on the firewall are required.

## Runtime management

### Cloudlink

Cloudlink status in the dashboard represents a device connection to the balenaCloud backend. This connection is the underlying technology that enables the following functionalities within balenaCloud, and as such we indicate the status of Cloudlink to help you to understand the status of your device and what functionality may or may not be available.

* [SSH access](/learn/manage/ssh-access) via CLI or web terminal
* [Public Device Url](/learn/manage/actions#public-device-url)
* [Device actions](/learn/manage/actions#device-actions) that allow controlling device state
* [Host OS Updates](/reference/os/updates/self-service)
* [Device Diagnostics](/reference/diagnostics)

Currently, Cloudlink uses [OpenVPN](https://openvpn.net/) as an underlying technology to achieve its functionality. Devices only connect outbound to Cloudlink, and all traffic over Cloudlink is encrypted with TLS.

Cloudlink disallows device-to-device traffic and prohibits outbound traffic to the Internet. If a device were compromised, this ensures that it cannot contaminate another device. To achieve this the Cloudlink service is configured to run with iptables default `FORWARD` policy set to `DROP` and we do not enable OpenVPN [--client-to-client](https://www.mankier.com/8/openvpn#--client-to-client) config option server side, so there is no way for the traffic between clients to traverse the interface(s).

Currently, authentication against Cloudlink is performed with API token authentication. API keys can be managed and revoked in the balena dashboard.

Cloudlink connection is optional and [can be disabled](/reference/supervisor/bandwidth-reduction) to conserve bandwidth or to remove the option of outside device control through the balenaCloud dashboard or API. When disabled, the Cloudlink connection will not be established from the device. No traffic will be transmitted or received through this channel. If desired, Cloudlink can be enabled and disabled programmatically so that it is turned on only when in active use (e.g. for interactive debugging) and disabled normally.

It is important to understand that due to its current design, Cloudlink is not architected for high availability. Cloudlink will periodically drop connections momentarily due to re-configuration or scaling, but it reconnects with the device automatically. For mission-critical workflows, we recommend designing your solution to be resilient to the potential brief unavailability of these specific interactive features. Furthermore, to protect overall platform stability for all users, devices that send/receive large amounts of data via Cloudlink continuously may be throttled.

### Support access

Device access is granted to a subset of balena employees to enable support and device troubleshooting. This access is controlled by the same SSH access mechanisms described above, and only SSH key access is permitted. Balena employees access devices only for user support and to maintain device state and uptime with permission from the customer.

If desired, this functionality can be disabled by removing the balena SSH public key from the device (or from the base image before flashing it onto the device). However, this will render the device inaccessible remotely for the purposes of support or repairs and updates to the base OS. Thus this should be done with extreme caution and only after careful consideration of the tradeoffs.

### Ports used

All communication between devices and the balena service are outbound from the device. Ports that are used by devices are:

| Port | Protocol | Status   | Description                                                                                                                                                                                                                                   |
| ---- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 53   | UDP      | Required | DNS: used by devices to resolve balena hostnames for connection to the balena service                                                                                                                                                         |
| 123  | UDP      | Required | NTP: used by devices to synchronize time                                                                                                                                                                                                      |
| 443  | TCP      | Required | <p>HTTPS: used by devices to poll balena for updates and to download releases and host OS updates.<br><br>Cloudlink: used by devices to connect to balena to provide real-status, control, and an interactive terminal (optional service)</p> |

### Device metadata

Devices contain metadata that identifies the device, fleet, and state of deployed software. This metadata is used to track the state of the device within the balena dashboard and to associate the device with a specific fleet.

Currently, metadata such as device identifiers or WiFi credentials are not encrypted on disk by default. This is because most commercially available devices do not support any form of hardware-level encryption, meaning that the decryption keys for this data would have to be stored in an accessible area of the device. Storing the keys with the encrypted data means that it is trivial for anyone with physical access to the device to decrypt the data at any point, rendering the encryption itself moot. If you do have a device that is capable of hardware-level encryption, please contact us to discuss your options.

## BalenaOS Software Bill of Materials (SBOM) and Vulnerability EXchange (VEX) files

BalenaOS provides Software Bill of Materials (SBOM) in the - machine readable, but human friendly - CycloneDX 1.4 json format. Those files can be used to determine the versions of all the components that compose the OS, and the known fixed vulnerabilities.

As we apply patches to fix vulnerabilities, comparing the version of a component to popular vulnerability databases such as the NVD is not enough. That's why we also release `vex` files along with the SBOM. Each vex file is related to a specific SBOM and **will list known vulnerabilities (CVE) that don't impact the release**, with an explanation when possible (i.e. the vulnerable code path is not accessible, the vulnerability has been patched, ...). Beware that this is **not an exhaustive list of known vulnerabilities** for the component. The vex file should only be used to filter down the list of vulnerabilities reported by SBOM vulnerability scanner.

A device release might contain multiple assets (the OS itself, a flasher image, the initramfs, ...), each will have their own `bom.json` and `vex.json`.

`bom.json` and `vex.json` files can be found in the asset list of an OS release page (under the `cyclonedx` folder); click the `HOST OS VERSION` of a device to go to that page).

SBOM and VEX are compatible with the cyclonedx ecosystem of software composition analysis. A list of tools (open-source and proprietary) can be found on [cyclonedx.org tool center](https://cyclonedx.org/tool-center/).

Note that availability of SBOM and VEX depends on device types and versions. If you can't find them for a release you care about, contact our support.

## Building images

The first step in deploying to a fleet of devices is to build a Docker image that contains everything necessary to run your application. While these images can be built locally, balena provides a powerful image builder that is more appropriate for most use cases. The builder for x86 images is hosted on AWS, while the builder for ARM images is hosted by a combination of AWS and Hetzner.

User code and data is pushed to the builders via git using SSH with public key encryption, ensuring that it is encrypted when sent to the balena builders. SSH keys are managed via the user dashboard or CLI tools.

Once user container images are built, they are pushed to the balena Docker registry. Only the balena builder has permission to write to the Docker registry, preventing tampering with the images from external sources.

## The API and backend

The balena API provides a central mechanism for authentication, requesting information, and making changes to the database. The API manages communication both internally among the backend services and externally for users and devices.

The API interface is based on the Open Data (OData) format. All requests are authenticated with an API token, which users access on the dashboard and can refresh via the API.

When possible, all backend services and components are run with user-level permissions. Where permission escalation is required, it is performed temporarily and de-escalated as soon as the escalated process is complete. This reduces the risk of a particular backend component being leveraged to compromise other components or other users' data and processes.

All software and images built within balena track the upstream projects directly and are rebuilt regularly to integrate the latest functionality and security updates. Internal services are run on Debian Linux and regularly rebuilt/updated.

HTTPS is mandatory for all services internally, meaning no data is transmitted unencrypted between balena servers.

The balena backend services, with the exception of the ARM image builders, are hosted on [Amazon Web Services](https://aws.amazon.com/) (AWS) using a Virtual Private Cloud (VPC). Using a VPC isolates balena from any other services hosted in AWS, allowing an additional layer of security and separation.

## Conclusion

The safety and security of your data and devices is crucial to us at balena. We do everything in our power to keep our services secure and transparent. If you have any questions about our security or want to engage in our [responsible disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure) process, please contact us at <security@balena.io> and we will answer in detail.


# Getting Help

If you find yourself stuck or confused, help is just a click away:

* The [balenaCloud](https://forums.balena.io/c/product-support) section of the forums is where our engineers address any issues you may be having with balena.
* You can read more about our approach to support [here](https://balena.io/support).
* You can learn about support access [here](https://docs.balena.io/learn/accounts/support-access/).


# Getting Started


# Getting started with ASUS Tinker Edge T

In this guide, we will help you get started with balenaCloud by:

* Setting up your **ASUS Tinker Edge T** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your ASUS Tinker Edge T device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **ASUS Tinker Edge T** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first ASUS Tinker Edge T.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for ASUS Tinker Edge T which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-asus-tinker-edge-t-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the ASUS Tinker Edge T.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Set the BOOT\_SELECT switch to the SD-CARD position. Connect power to the ASUS Tinker Edge T.
* Wait for the ASUS Tinker Edge T to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the ASUS Tinker Edge T.
* Set the BOOT\_SELECT switch to the eMMC position.,Remove and re-connect power to the ASUS Tinker Edge T. to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for ASUS Tinker Edge T](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/asus-tinker-edge-t/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    ASUS Tinker Edge T    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Auvidea JN30B Nano

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Auvidea JN30B Nano** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Auvidea JN30B Nano device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Auvidea JN30B Nano** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Auvidea JN30B Nano.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Auvidea JN30B Nano which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jn30b-nano-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Auvidea JN30B Nano, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jn30b-nano.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Auvidea JN30B Nano](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jn30b-nano/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Auvidea JN30B Nano    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with BeagleBone AI64

In this guide, we will help you get started with balenaCloud by:

* Setting up your **BeagleBone AI64** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your BeagleBone AI64 device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **BeagleBone AI64** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first BeagleBone AI64.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for BeagleBone AI64 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-beaglebone-ai64-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the BeagleBone AI64.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Power up the BeagleBone AI64 while holding down the small button near the SD slot. You need to keep it pressed until the blue LEDs start flashing wildly.
* Wait for the BeagleBone AI64 to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the BeagleBone AI64.
* Remove and re-connect power to the BeagleBone AI64 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for BeagleBone AI64](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/beaglebone-ai64/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    BeagleBone AI64    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with BeagleBone Black

In this guide, we will help you get started with balenaCloud by:

* Setting up your **BeagleBone Black** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Beaglebone Black](https://www.beagleboard.org/boards/beaglebone-black) or [Beaglebone Green](https://www.beagleboard.org/boards/seeedstudio-beaglebone-green).
* A 4GB or larger SD card. Both the Beaglebone Black and Green use a Micro SD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Speed_class_rating) of the card also matters - this determines its maximum transfer rate. We strongly recommend you get hold of a class 10 card or above.
* An ethernet cable or [WiFi adapter](https://github.com/balena-io/docs/blob/main/pages/hardware/wifi-dongles/README.md) to connect your device to the internet. The WiFi adapter for the Beaglebone Black is known to be unstable at moment, it is recommended that you use a usb WiFi adapter with a large external antenna.
* A mini USB cable the Beaglebone Black **OR** a micro USB cable for the Green.
* **\[Optional]** A 5VDC 1A power supply unit for the Beaglebone Black.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **BeagleBone Black** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first BeagleBone Black.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for BeagleBone Black which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-beaglebone-black-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the BeagleBone Black.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Power up the BeagleBone Black while holding down the small button near the SD slot. You need to keep it pressed until the blue LEDs start flashing wildly.
* Wait for the BeagleBone Black to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the BeagleBone Black.
* Remove and re-connect power to the BeagleBone Black to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for BeagleBone Black](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/beaglebone-black/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    BeagleBone Black    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab IOTDIN-iMX8P 1GB or 8GB DRAM

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab IOTDIN-iMX8P 1GB or 8GB DRAM** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Compulab IOTDIN-iMX8P 1GB or 8GB DRAM device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab IOTDIN-iMX8P 1GB or 8GB DRAM** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab IOTDIN-iMX8P 1GB or 8GB DRAM.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab IOTDIN-iMX8P 1GB or 8GB DRAM which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-iotdin-imx8p-d1d8-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Unpack the balenaOS image you downloaded from balena-cloud.
* Make sure the device is not powered and connect the PROG port to your PC using a micro USB cable.
* From a Linux-based host, use the [IOT-GATE-iMX8PLUS flashing tools](https://github.com/balena-os/iot-gate-imx8plus-flashtools) to write balenaOS on your device.
* After flashing is completed, disconnect the micro USB cable from the PROG port, power off the device and then power it back on.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab IOTDIN-iMX8P 1GB or 8GB DRAM](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/iotdin-imx8p-d1d8/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab IOTDIN-iMX8P 1GB or 8GB DRAM    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab IOTDIN-iMX8P 2GB or 4GB DRAM

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab IOTDIN-iMX8P 2GB or 4GB DRAM** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Compulab IOTDIN-iMX8P 2GB or 4GB DRAM device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab IOTDIN-iMX8P 2GB or 4GB DRAM** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab IOTDIN-iMX8P 2GB or 4GB DRAM.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab IOTDIN-iMX8P 2GB or 4GB DRAM which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-iotdin-imx8p-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Unpack the balenaOS image you downloaded from balena-cloud.
* Make sure the device is not powered and connect the PROG port to your PC using a micro USB cable.
* From a Linux-based host, use the [IOT-GATE-iMX8PLUS flashing tools](https://github.com/balena-os/iot-gate-imx8plus-flashtools) to write balenaOS on your device.
* After flashing is completed, disconnect the micro USB cable from the PROG port, power off the device and then power it back on.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab IOTDIN-iMX8P 2GB or 4GB DRAM](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/iotdin-imx8p/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab IOTDIN-iMX8P 2GB or 4GB DRAM    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab IOT-gate-imx8

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab IOT-gate-imx8** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

{% hint style="info" %}
Compulab IOT-gate-imx8 and Compulab IOT-GATE-iMX8PLUS have different provisioning instructions, make sure you're provisioning the right device!
{% endhint %}

* Your Compulab IOT-gate-imx8 device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab IOT-gate-imx8** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab IOT-gate-imx8.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab IOT-gate-imx8 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-iot-gate-imx8-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Compulab IOT-gate-imx8.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Compulab IOT-gate-imx8
* Wait for the Compulab IOT-gate-imx8 to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the USB key from the Compulab IOT-gate-imx8.
* Remove and re-connect power to the Compulab IOT-gate-imx8 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab IOT-gate-imx8](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/iot-gate-imx8/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab IOT-gate-imx8    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

{% hint style="info" %}
Compulab IOT-gate-imx8 and Compulab IOT-GATE-iMX8PLUS have different provisioning instructions, make sure you're provisioning the right device!
{% endhint %}

* Your Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-iot-gate-imx8plus-d1d8-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Unpack the balenaOS image you downloaded from balena-cloud.
* Make sure the device is not powered and connect the PROG port to your PC using a micro USB cable.
* From a Linux-based host, use the [IOT-GATE-iMX8PLUS flashing tools](https://github.com/balena-os/iot-gate-imx8plus-flashtools) to write balenaOS on your device.
* After flashing is completed, disconnect the micro USB cable from the PROG port, power off the device and then power it back on.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/iot-gate-imx8plus-d1d8/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab IOT-GATE-iMX8PLUS 1GB or 8GB DRAM    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

{% hint style="info" %}
Compulab IOT-gate-imx8 and Compulab IOT-GATE-iMX8PLUS have different provisioning instructions, make sure you're provisioning the right device!
{% endhint %}

* Your Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-iot-gate-imx8plus-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Unpack the balenaOS image you downloaded from balena-cloud.
* Make sure the device is not powered and connect the PROG port to your PC using a micro USB cable.
* From a Linux-based host, use the [IOT-GATE-iMX8PLUS flashing tools](https://github.com/balena-os/iot-gate-imx8plus-flashtools) to write balenaOS on your device.
* After flashing is completed, disconnect the micro USB cable from the PROG port, power off the device and then power it back on.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/iot-gate-imx8plus/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab IOT-GATE-iMX8PLUS 2GB or 4GB DRAM    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab MX8M

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab MX8M** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Compulab MX8M device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab MX8M** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab MX8M.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab MX8M which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-cl-som-imx8-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Compulab MX8M.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Compulab MX8M Press and hold SW5 followed by SW6 Release SW5 followed by SW6
* Wait for the Compulab MX8M to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Compulab MX8M.
* Remove and re-connect power to the Compulab MX8M to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab MX8M](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/cl-som-imx8/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab MX8M    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Compulab UCM-iMX93 Devkit

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Compulab UCM-iMX93 Devkit** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Compulab UCM-iMX93 Devkit device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Compulab UCM-iMX93 Devkit** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Compulab UCM-iMX93 Devkit.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Compulab UCM-iMX93 Devkit which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-ucm-imx93-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Compulab UCM-iMX93 Devkit.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Compulab UCM-iMX93 Devkit Press and hold SW3 followed by SW4 Release SW3 followed by SW4
* Wait for the Compulab UCM-iMX93 Devkit to finish flashing and shutdown. Please wait until ethernet LEDs are off for more than 5 seconds. An Ethernet cable needs pe plugged in for the LEDs to stay on during provisioning..
* Remove the SD card from the Compulab UCM-iMX93 Devkit.
* Remove and re-connect power to the Compulab UCM-iMX93 Devkit to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Compulab UCM-iMX93 Devkit](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/ucm-imx93/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Compulab UCM-iMX93 Devkit    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Coral Dev Board

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Coral Dev Board** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Coral Dev Board](https://coral.ai/products/dev-board/)
* A 4GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Class) of the card also matters - use the fastest you can find.
* A 2-3A (5V) USB Type-C power supply
* **\[Optional]** An ethernet cable.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Coral Dev Board** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Coral Dev Board.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Coral Dev Board which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-coral-dev-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Coral Dev Board.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Set the BOOT\_SELECT switch to the SD-CARD position Connect power to the Coral Dev Board
* Wait for the Coral Dev Board to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Coral Dev Board.
* Set the BOOT\_SELECT switch to the eMMC position,Remove and re-connect power to the Coral Dev Board to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Coral Dev Board](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/coral-dev/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Coral Dev Board    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Forecr DSBOARD-ORNX-LAN Orin Nano 8GB

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Forecr DSBOARD-ORNX-LAN Orin Nano 8GB** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Forecr DSBOARD-ORNX-LAN Orin Nano 8GB device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Forecr DSBOARD-ORNX-LAN Orin Nano 8GB** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Forecr DSBOARD-ORNX-LAN Orin Nano 8GB.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Forecr DSBOARD-ORNX-LAN Orin Nano 8GB which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-forecr-dsb-ornx-orin-nano-8gb-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* For balenaOS versions v6.1.16 and newer, please ensure your device is running UEFI firmware version 36.3. Check and update the [firmware version](https://docs.balena.io/learn/develop/hardware/jetson-orin#provisioning-jetson-orin) before proceeding. For balenaOS versions older than v6.1.16, please refer to the [Forecr DSBOARD-ORNX-LAN Orin Nano 8GB legacy flashing](https://github.com/balena-os/jetson-flash?tab=readme-ov-file) guide.
* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Forecr DSBOARD-ORNX-LAN Orin Nano 8GB.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Insert a NVME drive in the board and power up the Forecr DSBOARD-ORNX-LAN Orin Nano 8GB.
* Wait for the Forecr DSBOARD-ORNX-LAN Orin Nano 8GB to finish flashing and shutdown. Please wait until power LED is off.
* Remove the USB key from the Forecr DSBOARD-ORNX-LAN Orin Nano 8GB.
* Power up the Forecr DSBOARD-ORNX-LAN Orin Nano 8GB. If you have a display or a debug UART cable connected to the device, a progress bar will show up while the UEFI firmware is updated. Please do not interrupt this process by turning off power or rebooting the device. Once the firmware update completes, the Forecr DSBOARD-ORNX-LAN Orin Nano 8GB will reset automatically and no other steps are necessary to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Forecr DSBOARD-ORNX-LAN Orin Nano 8GB](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/forecr-dsb-ornx-orin-nano-8gb/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Forecr DSBOARD-ORNX-LAN Orin Nano 8GB    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Generic AARCH64

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Generic AARCH64** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

The Generic AARCH64 image is designed to run in a container on devices with a aarch64 architecture.

A few things to know before you begin:

* The Docker daemon needs to be running.
* The current user should have privileges to run Docker commands, as the script doesn't elevate them.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Generic AARCH64** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Generic AARCH64.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Generic AARCH64 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-generic-aarch64-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Generic AARCH64.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Generic AARCH64 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Generic AARCH64](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/generic-aarch64/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Generic AARCH64    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Generic x86\_64 (GPT)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Generic x86\_64 (GPT)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Generic x86\_64 (GPT) device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Generic x86\_64 (GPT)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Generic x86\_64 (GPT).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Generic x86\_64 (GPT) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-generic-amd64-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Generic x86\_64 (GPT).
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Ensure there are no other USB keys are inserted. Power on the Generic x86\_64 (GPT) with a keyboard connected. Press the F10 key while BIOS is loading to enter the boot menu. Select the USB key from the boot menu.
* Wait for the Generic x86\_64 (GPT) to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the USB key from the Generic x86\_64 (GPT).
* Power up the Generic x86\_64 (GPT) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Generic x86\_64 (GPT)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/generic-amd64/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Generic x86_64 (GPT)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Generic x86\_64 (legacy MBR)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Generic x86\_64 (legacy MBR)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Generic x86\_64 (legacy MBR) device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Generic x86\_64 (legacy MBR)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Generic x86\_64 (legacy MBR).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Generic x86\_64 (legacy MBR) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-genericx86-64-ext-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Generic x86\_64 (legacy MBR).
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Ensure there are no other USB keys are inserted. Power on the Generic x86\_64 (legacy MBR) with a keyboard connected. Press the F10 key while BIOS is loading to enter the boot menu. Select the USB key from the boot menu.
* Wait for the Generic x86\_64 (legacy MBR) to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the USB key from the Generic x86\_64 (legacy MBR).
* Power up the Generic x86\_64 (legacy MBR) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Generic x86\_64 (legacy MBR)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/genericx86-64-ext/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Generic x86_64 (legacy MBR)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Intel NUC

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Intel NUC** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* An [Intel NUC](https://www.intel.com/content/www/us/en/products/boards-kits/nuc.html) mini PC from Intel. Check out our [supported devices list](/reference/hardware/devices).
* A 4GB or larger USB thumb drive.
* A [HDMI](https://en.wikipedia.org/wiki/HDMI) enabled LCD screen and HDMI cable.
* A simple USB keyboard.
* A power supply unit for the NUC.
* An ethernet cable or [WiFi adapter](https://github.com/balena-io/docs/blob/main/pages/reference/hardware/wifi-dongles/README.md) to connect your device to the internet.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Intel NUC** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Intel NUC.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Intel NUC which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-intel-nuc-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Intel NUC.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Ensure there are no other USB keys are inserted. Power on the Intel NUC with a keyboard connected. Press the F10 key while BIOS is loading to enter the boot menu. Select the USB key from the boot menu.
* Wait for the Intel NUC to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the USB key from the Intel NUC.
* Power up the Intel NUC to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Intel NUC](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/intel-nuc/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Intel NUC    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Kontron i.MX8M Mini

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Kontron i.MX8M Mini** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Kontron i.MX8M Mini device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Kontron i.MX8M Mini** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Kontron i.MX8M Mini.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Kontron i.MX8M Mini which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-kontron-mx8mm-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Kontron i.MX8M Mini.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Kontron i.MX8M Mini
* Wait for the Kontron i.MX8M Mini to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Kontron i.MX8M Mini.
* Remove and re-connect power to the Kontron i.MX8M Mini to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Kontron i.MX8M Mini](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/kontron-mx8mm/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Kontron i.MX8M Mini    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with NanoPi R2S

In this guide, we will help you get started with balenaCloud by:

* Setting up your **NanoPi R2S** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your NanoPi R2S device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **NanoPi R2S** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first NanoPi R2S.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for NanoPi R2S which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-nanopi-r2s-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the NanoPi R2S.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect the NanoPi R2S to the internet, then power it up to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for NanoPi R2S](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/nanopi-r2s/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    NanoPi R2S    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nitrogen8M Mini SBC

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nitrogen8M Mini SBC** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nitrogen8M Mini SBC device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nitrogen8M Mini SBC** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nitrogen8M Mini SBC.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nitrogen8M Mini SBC which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-nitrogen8mm-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Nitrogen8M Mini SBC.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Nitrogen8M Mini SBC
* Wait for the Nitrogen8M Mini SBC to finish flashing and shutdown.
* Remove the SD card from the Nitrogen8M Mini SBC.
* Remove and re-connect power to the Nitrogen8M Mini SBC to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nitrogen8M Mini SBC](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/nitrogen8mm/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nitrogen8M Mini SBC    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson AGX Orin Devkit 32GB

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson AGX Orin Devkit 32GB** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson AGX Orin Devkit 32GB device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson AGX Orin Devkit 32GB** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson AGX Orin Devkit 32GB.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson AGX Orin Devkit 32GB which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-agx-orin-devkit-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson AGX Orin Devkit 32GB, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-agx-orin-devkit.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson AGX Orin Devkit 32GB](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-agx-orin-devkit/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson AGX Orin Devkit 32GB    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson AGX Orin Devkit 64GB

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson AGX Orin Devkit 64GB** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson AGX Orin Devkit 64GB device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson AGX Orin Devkit 64GB** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson AGX Orin Devkit 64GB.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson AGX Orin Devkit 64GB which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-agx-orin-devkit-64gb-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* For balenaOS versions v6.1.16 and newer, please ensure your device is running UEFI firmware version 36.3.0. Check and update the [firmware version](https://docs.balena.io/learn/develop/hardware/jetson-orin/jetson-agx-orin-devkit-64gb/#checking-your-jetson-orins-uefi-firmware-version) before proceeding. For balenaOS versions older than v6.1.16, please refer to the [Nvidia Jetson AGX Orin Devkit 64GB legacy flashing](https://github.com/balena-os/jetson-flash?tab=readme-ov-file) guide.
* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Nvidia Jetson AGX Orin Devkit 64GB.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Power on the Nvidia Jetson AGX Orin Devkit 64GB. NOTE: Only If your device is already flashed with a balenaOS version older than v6.1.16, power it on and interrupt booting by pressing the 'Esc' key when prompted by the UEFI firmware. Enter the Boot Manager Menu of the UEFI firmware and select the attached USB key as boot media, to trigger the provisioning process.
* Wait for the Nvidia Jetson AGX Orin Devkit 64GB to finish flashing and shutdown. Please wait until power LED is off.
* Remove the USB key from the Nvidia Jetson AGX Orin Devkit 64GB.
* Power up the Nvidia Jetson AGX Orin Devkit 64GB. A progress bar will show up on the display while the UEFI firmware is updated. Please do not interrupt this process by turning off power or rebooting the device. Once the firmware update completes, the Nvidia Jetson AGX Orin Devkit 64GB will reset automatically and no other steps are necessary to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson AGX Orin Devkit 64GB](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-agx-orin-devkit-64gb/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson AGX Orin Devkit 64GB    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Nano 2GB Devkit SD

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Nano 2GB Devkit SD** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson Nano 2GB Devkit SD device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Nano 2GB Devkit SD** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Nano 2GB Devkit SD.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Nano 2GB Devkit SD which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-nano-2gb-devkit-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson Nano 2GB Devkit SD, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-nano-2gb-devkit.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Nano 2GB Devkit SD](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-nano-2gb-devkit/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Nano 2GB Devkit SD    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Nano eMMC

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Nano eMMC** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Nvidia Jetson Nano eMMC](https://developer.nvidia.com/embedded/jetson-nano) and it's devkit carrier board. See our [supported devices list](/reference/hardware/devices) for other boards.
* A micro USB cable to flash the device.
* A compatible power supply.
* An ethernet cable (the Jetson Nano eMMC module does not include WiFi but it can be added via an optional USB dongle).
* The [Jetson-Flash](https://github.com/balena-os/jetson-flash) utility.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Nano eMMC** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Nano eMMC.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Nano eMMC which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-nano-emmc-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson Nano eMMC, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-nano-emmc.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Nano eMMC](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-nano-emmc/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Nano eMMC    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Nano SD-CARD

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Nano SD-CARD** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Nvidia Jetson Nano developer kit](https://developer.nvidia.com/embedded/buy/jetson-nano-devkit)
* A 16GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Class) of the card also matters - UHS speed class I or above is recommended.
* An ethernet cable (the Jetson Nano developer kit does not include WiFi but it can be added via an optional mPCIe card or USB dongle).
* Compatible power supply - a 5V 4A barrel jack PSU is recommended, but you can also use a 5V 2.5A micro USB supply.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Nano SD-CARD** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Nano SD-CARD.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Nano SD-CARD which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-nano-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson Nano SD-CARD, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-nano.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Nano SD-CARD](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-nano/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Nano SD-CARD    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-orin-nano-devkit-nvme-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* For balenaOS versions v6.1.16 and newer, please ensure your device is running UEFI firmware version 36.3.0. Check and update the [firmware version](https://docs.balena.io/learn/develop/hardware/jetson-orin/jetson-orin-nano-devkit-nvme/#checking-your-jetson-orins-uefi-firmware-version) before proceeding. For balenaOS versions older than v6.1.16, please refer to the [Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME legacy flashing](https://github.com/balena-os/jetson-flash?tab=readme-ov-file) guide.
* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Insert a NVME drive in the Devkit and power up the Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME.
* Wait for the Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME to finish flashing and shutdown. Please wait until power LED is off.
* Remove the USB key from the Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME.
* Power up the Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME. If you have a display or a debug UART cable connected to the device, a progress bar will show up while the UEFI firmware is updated. Please do not interrupt this process by turning off power or rebooting the device. Once the firmware update completes, the Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME will reset automatically and no other steps are necessary to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-orin-nano-devkit-nvme/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Orin Nano 8GB (SD) Devkit NVME    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-orin-nx-xavier-nx-devkit-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* For balenaOS versions v6.1.16 and newer, please ensure your device is running UEFI firmware version 36.3.0. Check and update the [firmware version](https://docs.balena.io/learn/develop/hardware/jetson-orin/jetson-orin-nx-xavier-nx-devkit/#checking-your-jetson-orins-uefi-firmware-version) before proceeding. For balenaOS versions older than v6.1.16, please refer to the [Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME legacy flashing](https://github.com/balena-os/jetson-flash?tab=readme-ov-file) guide.
* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Insert a NVME drive in the Devkit and power up the Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME.
* Wait for the Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME to finish flashing and shutdown. Please wait until power LED is off.
* Remove the USB key from the Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME.
* Power up the Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME. A progress bar will show up on the display while the UEFI firmware is updated. Please do not interrupt this process by turning off power or rebooting the device. Once the firmware update completes, the Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME will reset automatically and no other steps are necessary to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-orin-nx-xavier-nx-devkit/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson TX2

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson TX2** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Nvidia Jetson TX2](https://developer.nvidia.com/embedded/buy/jetson-tx2), along with the baseboard that allows flashing from an SD card.
* A 4GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Speed_class_rating) of the card also matters - use the fastest you can find.
* An ethernet cable.
* Compatible power supply.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson TX2** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson TX2.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson TX2 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-tx2-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Nvidia Jetson TX2.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Nvidia Jetson TX2 and press and hold the POWER push button for 1 second
* Wait for the Nvidia Jetson TX2 to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Nvidia Jetson TX2.
* Remove and re-connect power to the Nvidia Jetson TX2 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson TX2](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-tx2/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson TX2    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson TX2 NX (with Xavier NX Devkit)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson TX2 NX (with Xavier NX Devkit)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson TX2 NX (with Xavier NX Devkit) device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson TX2 NX (with Xavier NX Devkit)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson TX2 NX (with Xavier NX Devkit).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson TX2 NX (with Xavier NX Devkit) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-tx2-nx-devkit-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson TX2 NX (with Xavier NX Devkit), follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-tx2-nx-devkit.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson TX2 NX (with Xavier NX Devkit)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-tx2-nx-devkit/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson TX2 NX (with Xavier NX Devkit)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Xavier

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Xavier** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson Xavier device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Xavier** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Xavier.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Xavier which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-xavier-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson Xavier, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-xavier.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Xavier](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-xavier/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Xavier    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Xavier NX Devkit eMMC

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Xavier NX Devkit eMMC** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Nvidia Jetson Xavier NX Devkit eMMC device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Xavier NX Devkit eMMC** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Xavier NX Devkit eMMC.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Xavier NX Devkit eMMC which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-xavier-nx-devkit-emmc-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson Xavier NX Devkit eMMC, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-xavier-nx-devkit-emmc.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Xavier NX Devkit eMMC](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-xavier-nx-devkit-emmc/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Xavier NX Devkit eMMC    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Nvidia Jetson Xavier NX Devkit SD-CARD

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Nvidia Jetson Xavier NX Devkit SD-CARD** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Nvidia Jetson Xavier NX developer kit](https://developer.nvidia.com/embedded/jetson-xavier-nx-devkit)
* A 16GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Class) of the card also matters - UHS speed class I or above is recommended.
* Compatible power supply.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Nvidia Jetson Xavier NX Devkit SD-CARD** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Nvidia Jetson Xavier NX Devkit SD-CARD.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Nvidia Jetson Xavier NX Devkit SD-CARD which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-xavier-nx-devkit-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* To provision Nvidia Jetson Xavier NX Devkit SD-CARD, follow the instructions using our [Jetson Flash tool](https://github.com/balena-os/jetson-flash/blob/master/docs/jetson-xavier-nx-devkit.md) to make the process more streamlined.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Nvidia Jetson Xavier NX Devkit SD-CARD](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-xavier-nx-devkit/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Nvidia Jetson Xavier NX Devkit SD-CARD    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with NXP i.MX8M Mini LPDDR4 EVK

In this guide, we will help you get started with balenaCloud by:

* Setting up your **NXP i.MX8M Mini LPDDR4 EVK** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your NXP i.MX8M Mini LPDDR4 EVK device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **NXP i.MX8M Mini LPDDR4 EVK** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first NXP i.MX8M Mini LPDDR4 EVK.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for NXP i.MX8M Mini LPDDR4 EVK which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-imx8mm-lpddr4-evk-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the NXP i.MX8M Mini LPDDR4 EVK.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the NXP i.MX8M Mini LPDDR4 EVK
* Wait for the NXP i.MX8M Mini LPDDR4 EVK to finish flashing and shutdown.
* Remove the SD card from the NXP i.MX8M Mini LPDDR4 EVK.
* Remove and re-connect power to the NXP i.MX8M Mini LPDDR4 EVK to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for NXP i.MX8M Mini LPDDR4 EVK](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/imx8mm-lpddr4-evk/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    NXP i.MX8M Mini LPDDR4 EVK    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Owasys owa5X

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Owasys owa5X** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Owasys owa5X device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Owasys owa5X** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Owasys owa5X.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Owasys owa5X which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-owa5x-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Owasys owa5X.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Erase internal NAND content. Insert an SD card with a bootable image.
* Wait for the Owasys owa5X to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Owasys owa5X.
* Remove and re-connect power to the Owasys owa5X to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Owasys owa5X](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/owa5x/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Owasys owa5X    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with phyBOARD-AM62x

In this guide, we will help you get started with balenaCloud by:

* Setting up your **phyBOARD-AM62x** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your phyBOARD-AM62x device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **phyBOARD-AM62x** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first phyBOARD-AM62x.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for phyBOARD-AM62x which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-phyboard-lyra-am62xx-2-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the phyBOARD-AM62x.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Configure S5 and S6 to set the boot mode to SD card. Plug in the microSD card and connect power to the phyBOARD-AM62x
* Wait for the phyBOARD-AM62x to finish flashing and shutdown. Please wait until LEDs D11 and D12 are off.
* Remove the SD card from the phyBOARD-AM62x.
* Configure S5 and S6 to set the boot mode to eMMC. Remove and re-connect power to the phyBOARD-AM62x. to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for phyBOARD-AM62x](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/phyboard-lyra-am62xx-2/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    phyBOARD-AM62x    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi 2

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi 2** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Raspberry Pi 2 model B](https://www.raspberrypi.org/products/raspberry-pi-2-model-b/). See our [supported devices list](/reference/hardware/devices) for other boards.
* A 4GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Speed_class_rating) of the card also matters - use the fastest you can find.
* An ethernet cable or WiFi adapter. Check our [list of supported WiFi adapters](https://github.com/balena-io/docs/blob/main/pages/hardware/wifi-dongles/README.md).
* A micro USB cable (for power supply).
* A [2A micro USB power supply](https://www.raspberrypi.org/products/raspberry-pi-universal-power-supply/).
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi 2** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi 2.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi 2 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberry-pi2-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi 2.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi 2 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi 2](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberry-pi2/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi 2    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi 3

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi 3** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/) or [B+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/). See our [supported devices list](/reference/hardware/devices) for other boards.
* A 4GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Speed_class_rating) of the card also matters - use the fastest you can find.
* A micro USB cable (for power supply).
* A [2A micro USB power supply](https://www.raspberrypi.org/products/raspberry-pi-universal-power-supply/).
* **\[Optional]** An ethernet cable.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi 3** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi 3.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi 3 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypi3-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi 3.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi 3 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi 3](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypi3/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi 3    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi 3 (using 64bit OS)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi 3 (using 64bit OS)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/) or [B+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/). See our [supported devices list](/reference/hardware/devices) for other boards.
* A 4GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Speed_class_rating) of the card also matters - use the fastest you can find.
* A micro USB cable (for power supply).
* A [2A micro USB power supply](https://www.raspberrypi.org/products/raspberry-pi-universal-power-supply/).
* **\[Optional]** An ethernet cable.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi 3 (using 64bit OS)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi 3 (using 64bit OS).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi 3 (using 64bit OS) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypi3-64-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi 3 (using 64bit OS).

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi 3 (using 64bit OS) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi 3 (using 64bit OS)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypi3-64/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi 3 (using 64bit OS)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi 4 (using 64bit OS)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi 4 (using 64bit OS)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A [Raspberry Pi 4 Model B](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/). See our [supported devices list](/reference/hardware/devices) for other boards.
* A 4GB or larger microSD card. The [speed class](https://en.wikipedia.org/wiki/Secure_Digital#Speed_class_rating) of the card also matters - use the fastest you can find.
* A USB-C cable (for power supply, rated at 3A).
* A [3A USB-C power supply](https://www.raspberrypi.org/products/type-c-power-supply/).
* **\[Optional]** An ethernet cable.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

If you intend to use [hardware Rev 1.5](https://github.com/balena-io/docs/blob/main/pages/faq/troubleshooting/raspberrypi4-64/README.md#balenaos-boot-issues-with-new-hardware-revision-of-rpi4) of the Raspberry Pi 4 Model B, then we recommend using recent versions of balenaOS (v2.88.5+rev1 or later). Earlier balenaOS versions won’t boot due to [changes in this hardware revision](https://forums.raspberrypi.com/viewtopic.php?t=329299). Refer to [instructions](https://github.com/balena-io/docs/blob/main/pages/faq/troubleshooting/raspberrypi4-64/README.md#balenaos-boot-issues-with-new-hardware-revision-of-rpi4) for identifying the hardware revision of your Raspberry Pi 4 Model B.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi 4 (using 64bit OS)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi 4 (using 64bit OS).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi 4 (using 64bit OS) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypi4-64-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi 4 (using 64bit OS).

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi 4 (using 64bit OS) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi 4 (using 64bit OS)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypi4-64/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi 4 (using 64bit OS)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi 5 & CM5

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi 5 & CM5** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Raspberry Pi 5 & CM5 device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi 5 & CM5** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi 5 & CM5.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi 5 & CM5 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypi5-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi 5 & CM5.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi 5 & CM5 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi 5 & CM5](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypi5/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi 5 &amp; CM5    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi CM4 IO Board

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi CM4 IO Board** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Raspberry Pi CM4 IO Board device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi CM4 IO Board** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi CM4 IO Board.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi CM4 IO Board which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypicm4-ioboard-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Fit the jumper to disable eMMC boot on J2 and connect the Raspberry Pi CM4 IO Board's microUSB port to your PC. Power the board and use [usbboot](https://github.com/raspberrypi/usbboot) to put the eMMC in mass storage mode.
* Write the balenaOS file you downloaded to the Raspberry Pi CM4 IO Board. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Disconnect the power source and eMMC boot jumper.
* Remove and re-connect power to the Raspberry Pi CM4 IO Board. to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi CM4 IO Board](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypicm4-ioboard/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi CM4 IO Board    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi (v1 / Zero / Zero W)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi (v1 / Zero / Zero W)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A Raspberry Pi 1 (model \[B, B+]\[bplus], or \[A+]\[aplus]), \[Zero]\[zero], or \[Zero W]\[zerow]. See our [supported devices list](/reference/hardware/devices) for other boards.
* A 4GB or larger SD card. All models of Raspberry Pi, except older model Bs, uses a microSD card. The \[speed class]\[sdSpeed] of the card also matters - use the fastest you can find.
* An ethernet cable or WiFi adapter (not needed for the Zero W). Check our \[list of supported WiFi adapters]\[wifiAdapters].
* A micro USB cable.
* A \[2A micro USB power supply]\[psu].
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

\[aplus]:{{ $links.raspberrypi.aplus }} \[bplus]:{{ $links.raspberrypi.bplus }} \[zero]:<https://www.raspberrypi.org/products/raspberry-pi-zero/> \[zerow]:<https://www.raspberrypi.org/products/raspberry-pi-zero-w/> \[psu]:<https://www.raspberrypi.org/products/raspberry-pi-universal-power-supply/> \[sdSpeed]:<https://en.wikipedia.org/wiki/Secure\\_Digital#Speed\\_class\\_rating> \[wifiAdapters]:/hardware/wifi-dongles/ \[supportedDevicesList]:/hardware/devices/

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi (v1 / Zero / Zero W)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi (v1 / Zero / Zero W).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi (v1 / Zero / Zero W) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberry-pi-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi (v1 / Zero / Zero W).

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi (v1 / Zero / Zero W) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi (v1 / Zero / Zero W)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberry-pi/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi (v1 / Zero / Zero W)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Raspberry Pi Zero 2 W (64bit)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Raspberry Pi Zero 2 W (64bit)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Raspberry Pi Zero 2 W (64bit) device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Raspberry Pi Zero 2 W (64bit)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Raspberry Pi Zero 2 W (64bit).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Raspberry Pi Zero 2 W (64bit) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypi0-2w-64-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Raspberry Pi Zero 2 W (64bit).

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the Raspberry Pi Zero 2 W (64bit) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Raspberry Pi Zero 2 W (64bit)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypi0-2w-64/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Raspberry Pi Zero 2 W (64bit)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Revolution Pi Connect 4

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Revolution Pi Connect 4** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Revolution Pi Connect 4 device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Revolution Pi Connect 4** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Revolution Pi Connect 4.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Revolution Pi Connect 4 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-revpi-connect-4-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* While not having the Revolution Pi Connect 4 board powered, connect your system to the board's USB port via a micro-USB cable. Power on the Revolution Pi Connect 4.
* Write the balenaOS file you downloaded to the Revolution Pi Connect 4. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Power off the Revolution Pi Connect 4 and unplug the micro-USB cable
* Remove and re-connect power to the Revolution Pi Connect 4 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Revolution Pi Connect 4](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/revpi-connect-4/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Revolution Pi Connect 4    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Revolution Pi Connect S

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Revolution Pi Connect S** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Revolution Pi Connect S device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Revolution Pi Connect S** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Revolution Pi Connect S.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Revolution Pi Connect S which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-revpi-connect-s-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* While not having the Revolution Pi Connect S board powered, connect your system to the board's USB port via a micro-USB cable. Power on the Revolution Pi Connect S.
* Write the balenaOS file you downloaded to the Revolution Pi Connect S. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Power off the Revolution Pi Connect S and unplug the micro-USB cable
* Remove and re-connect power to the Revolution Pi Connect S to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Revolution Pi Connect S](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/revpi-connect-s/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Revolution Pi Connect S    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Robustel EG5120 i.MX8MP

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Robustel EG5120 i.MX8MP** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Robustel EG5120 i.MX8MP device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Robustel EG5120 i.MX8MP** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Robustel EG5120 i.MX8MP.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Robustel EG5120 i.MX8MP which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-eg5120-imx8mp-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Robustel EG5120 i.MX8MP.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the Robustel EG5120 i.MX8MP
* Wait for the Robustel EG5120 i.MX8MP to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Robustel EG5120 i.MX8MP.
* Remove and re-connect power to the Robustel EG5120 i.MX8MP to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Robustel EG5120 i.MX8MP](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/eg5120-imx8mp/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Robustel EG5120 i.MX8MP    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with ROCK Pi 4B

In this guide, we will help you get started with balenaCloud by:

* Setting up your **ROCK Pi 4B** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your ROCK Pi 4B device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **ROCK Pi 4B** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first ROCK Pi 4B.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for ROCK Pi 4B which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-rockpi-4b-rk3399-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the ROCK Pi 4B.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Connect power to the ROCK Pi 4B
* Wait for the ROCK Pi 4B to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the ROCK Pi 4B.
* Remove and re-connect power to the ROCK Pi 4B to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for ROCK Pi 4B](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/rockpi-4b-rk3399/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    ROCK Pi 4B    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Rocktech ISG 503

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Rocktech ISG 503** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Rocktech ISG 503 device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Rocktech ISG 503** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Rocktech ISG 503.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Rocktech ISG 503 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-isg-503-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Rocktech ISG 503.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Power on the Rocktech ISG 503
* Wait for the Rocktech ISG 503 to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Rocktech ISG 503.
* Remove and re-connect power to the Rocktech ISG 503 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Rocktech ISG 503](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/isg-503/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Rocktech ISG 503    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Seeed reComputer J3010 Jetson Orin Nano 4GB

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Seeed reComputer J3010 Jetson Orin Nano 4GB** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Seeed reComputer J3010 Jetson Orin Nano 4GB device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Seeed reComputer J3010 Jetson Orin Nano 4GB** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Seeed reComputer J3010 Jetson Orin Nano 4GB.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Seeed reComputer J3010 Jetson Orin Nano 4GB which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-orin-nano-seeed-j3010-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* For balenaOS versions v6.1.16 and newer, please ensure your device is running UEFI firmware version 36.3.0. Check and update the [firmware version](https://docs.balena.io/learn/develop/hardware/jetson-orin/jetson-orin-nano-seeed-j3010/#checking-your-jetson-orins-uefi-firmware-version) before proceeding. For balenaOS versions older than v6.1.16, please refer to the [Seeed reComputer J3010 Jetson Orin Nano 4GB legacy flashing](https://github.com/balena-os/jetson-flash?tab=readme-ov-file) guide.
* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Seeed reComputer J3010 Jetson Orin Nano 4GB.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Insert a NVME drive in the Devkit and power up the Seeed reComputer J3010 Jetson Orin Nano 4GB
* Wait for the Seeed reComputer J3010 Jetson Orin Nano 4GB to finish flashing and shutdown. Please wait until power LED is off.
* Remove the USB key from the Seeed reComputer J3010 Jetson Orin Nano 4GB.
* Power up the Seeed reComputer J3010 Jetson Orin Nano 4GB. If you have a display or a debug UART cable connected to the device, a progress bar will show up while the UEFI firmware is updated. Please do not interrupt this process by turning off power or rebooting the device. Once the firmware update completes, the Seeed reComputer J3010 Jetson Orin Nano 4GB will reset automatically and no other steps are necessary to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Seeed reComputer J3010 Jetson Orin Nano 4GB](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-orin-nano-seeed-j3010/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Seeed reComputer J3010 Jetson Orin Nano 4GB    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-jetson-orin-nx-seeed-j4012-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* For balenaOS versions v6.1.16 and newer, please ensure your device is running UEFI firmware version 36.3.0. Check and update the [firmware version](https://docs.balena.io/learn/develop/hardware/jetson-orin/jetson-orin-nx-seeed-j4012/#checking-your-jetson-orins-uefi-firmware-version) before proceeding. For balenaOS versions older than v6.1.16, please refer to the [Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB legacy flashing](https://github.com/balena-os/jetson-flash?tab=readme-ov-file) guide.
* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Insert a NVME drive in the Devkit and power up the Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB.
* Wait for the Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB to finish flashing and shutdown. Please wait until power LED is off.
* Remove the USB key from the Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB.
* Power up the Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB. If you have a display or a debug UART cable connected to the device, a progress bar will show up while the UEFI firmware is updated. Please do not interrupt this process by turning off power or rebooting the device. Once the firmware update completes, the Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB will reset automatically and no other steps are necessary to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/jetson-orin-nx-seeed-j4012/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Seeed reComputer J4012 (Classic) Jetson Orin NX 16GB    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with UniPi Neuron (Raspberry Pi 4)

In this guide, we will help you get started with balenaCloud by:

* Setting up your **UniPi Neuron (Raspberry Pi 4)** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your UniPi Neuron (Raspberry Pi 4) device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **UniPi Neuron (Raspberry Pi 4)** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first UniPi Neuron (Raspberry Pi 4).

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for UniPi Neuron (Raspberry Pi 4) which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-raspberrypi4-unipi-neuron-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the UniPi Neuron (Raspberry Pi 4).

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* Connect power to the UniPi Neuron (Raspberry Pi 4) to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for UniPi Neuron (Raspberry Pi 4)](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/raspberrypi4-unipi-neuron/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    UniPi Neuron (Raspberry Pi 4)    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with UP Board

In this guide, we will help you get started with balenaCloud by:

* Setting up your **UP Board** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* An [UP board](https://www.up-board.org/), [UP squared](https://www.up-board.org/upsquared/specifications), or [UP core](https://www.up-board.org/upcore/specifications). See our [supported devices list](https://github.com/balena-io/docs/blob/main/pages/hardware/devices/README.md) for other supported boards.
* A 4GB or larger {{ $device.bootMedia }}.
* An ethernet cable or WiFi adapter. Check our [list of supported WiFi adapters](https://github.com/balena-io/docs/blob/main/pages/hardware/wifi-dongles/README.md).
* A [5V @4A UPboard power supply](https://up-shop.org/default/accessory/power-adapter.html).
* A USB keyboard.
* An HDMI LCD screen.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **UP Board** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first UP Board.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for UP Board which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-up-board-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the USB key to the host machine.
* Write the balenaOS file you downloaded to the USB key. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the USB key from the host machine.
* Insert the freshly flashed USB key into the UP Board.
* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Power on the UP Board with a keyboard connected. Press the F7 key while BIOS is loading to enter the boot menu. Select the "UEFI:" option from the boot menu.
* Wait for the UP Board to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the USB key from the UP Board.
* Power up the UP Board to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for UP Board](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/up-board/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    UP Board    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Variscite DART-MX8M

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Variscite DART-MX8M** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Variscite DART-MX8M device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Variscite DART-MX8M** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Variscite DART-MX8M.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Variscite DART-MX8M which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-imx8m-var-dart-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Variscite DART-MX8M.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Set the SW7 BOOT-SELECT switch to SD-CARD. Connect power to the Variscite DART-MX8M.
* Wait for the Variscite DART-MX8M to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Variscite DART-MX8M.
* Set the SW7 BOOT-SELECT switch to eMMC.,Remove and re-connect power to the Variscite DART-MX8M. to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Variscite DART-MX8M](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/imx8m-var-dart/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Variscite DART-MX8M    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Variscite DART-MX8M Mini

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Variscite DART-MX8M Mini** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Variscite DART-MX8M Mini device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Variscite DART-MX8M Mini** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Variscite DART-MX8M Mini.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Variscite DART-MX8M Mini which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-imx8mm-var-dart-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Variscite DART-MX8M Mini.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Set the SW7 BOOT-SELECT switch to EXT. Connect power to the Variscite DART-MX8M Mini.
* Wait for the Variscite DART-MX8M Mini to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Variscite DART-MX8M Mini.
* Set the SW7 BOOT-SELECT switch to INT.,Remove and re-connect power to the Variscite DART-MX8M Mini. to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Variscite DART-MX8M Mini](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/imx8mm-var-dart/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Variscite DART-MX8M Mini    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Variscite VAR-SOM-MX6

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Variscite VAR-SOM-MX6** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* A \[Variscite VAR-SOM-MX6]\[device-link] module. See our [supported devices list](https://github.com/balena-io/docs/blob/main/pages/hardware/devices/README.md) for other boards.
* A carrier board, in this case the [VAR-SOLO Customboard](https://www.variscite.com/products/single-board-computers/var-solocustomboard/)
* A micro SD card.
* **\[Optional]** An ethernet cable.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup).

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Variscite VAR-SOM-MX6** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Variscite VAR-SOM-MX6.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Variscite VAR-SOM-MX6 which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-var-som-mx6-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Variscite VAR-SOM-MX6.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Set the BOOT-SELECT switch to eMMC. Connect power to the Variscite VAR-SOM-MX6.
* Wait for the Variscite VAR-SOM-MX6 to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Variscite VAR-SOM-MX6.
* Set the BOOT-SELECT switch to NAND,Remove and re-connect power to the Variscite VAR-SOM-MX6 to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Variscite VAR-SOM-MX6](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/var-som-mx6/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Variscite VAR-SOM-MX6    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Getting started with Variscite VAR-SOM-MX8M-MINI Devkit

In this guide, we will help you get started with balenaCloud by:

* Setting up your **Variscite VAR-SOM-MX8M-MINI Devkit** device and bringing it online on the balenaCloud dashboard.
* Deploying a *hello world* project on the device in your language of choice.
* Developing the sample project: making changes and testing them on the device in real-time.

Once you've completed this getting started guide to balena, you'll be equipped with the fundamentals needed to continue developing your application using balenaCloud and be on the path to deploying fleets of devices to production. If you are looking for definitions of certain terms, refer to the [glossary](/learn/more/glossary).

## What you'll need

* Your Variscite VAR-SOM-MX8M-MINI Devkit device you want to get started with. Check out all of our [supported devices](/reference/hardware/devices).
* A tool to flash the new operating system on the device. We recommend [Etcher](https://www.balena.io/etcher).
* A way to connect the device to the internet, either through wifi (if available) or ethernet cable.
* A method of reliably powering the device.
* A [balenaCloud account](https://dashboard.balena-cloud.com/signup). BalenaCloud is free for up to 10 devices and requires no payment method to sign up.
* Install [balena CLI](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md) to develop & manage your device on balenaCloud.

## Create a fleet

A fleet is a group of devices that share the same [architecture](/reference/hardware/devices) and run the same code. Devices are added to fleets and can be moved between fleets at any time.

To create your first fleet, log into your [balenaCloud dashboard](https://dashboard.balena-cloud.com/) and click the **Create fleet** button.

<figure><img src="/files/8yuMnp8emk9dssEr7jrU" alt="Create a fleet"><figcaption></figcaption></figure>

Enter a fleet name, select the **Variscite VAR-SOM-MX8M-MINI Devkit** device type, and click **Create new fleet**:

<figure><img src="/files/lJHfBUwlnQusTDxTLvKK" alt=""><figcaption></figcaption></figure>

You'll then be redirected to the summary of the newly created fleet, where you can add your first Variscite VAR-SOM-MX8M-MINI Devkit.

## Add a device and download OS

<figure><img src="/files/g6Aj1nNXgrAlCZGJsyX2" alt="Add a device"><figcaption></figcaption></figure>

balenaCloud builds a custom balenaOS image configured for Variscite VAR-SOM-MX8M-MINI Devkit which allows the device to provision and join the new fleet you created automatically. Start by clicking **Add device** on the fleet summary. Your device type will be preselected here since you already chose it when creating the fleet. Other device types of the same [architecture](/reference/hardware/devices) can also be picked to join the fleet.

<figure><img src="/files/bHXCQSdi3iaWyhJRbxJa" alt="Add new device"><figcaption></figcaption></figure>

Select an OS type of *balenaOS*, and you will see a list of available balenaOS versions with the latest preselected. Choose a **Development** version of the OS. The production OS does not facilitate the development workflow we'll be using. Find out more about the [differences between Development and Production images](/reference/os/overview#development-vs-production-images).

<figure><img src="/files/Z5r47M0uLQ5iEbdRILwW" alt="Network configuration"><figcaption></figcaption></figure>

Select the type of network connection you'll be using: *Ethernet Only* or *Wifi + Ethernet*. A network connection is required to allow the device to connect to balenaCloud. Selecting *Wifi + Ethernet* allows you to enter a *Wifi SSID* and *Wifi Passphrase* which is then built into the image.

<figure><img src="/files/IuQonGUezYdfUddRBRu7" alt="Download Image Step 1" width="375"><figcaption></figcaption></figure>

Click the arrow by the **Flash** button. You'll see several options.

<figure><img src="/files/4GeRhGzduFWSGeI5fALZ" alt="Download Image Step 2" width="375"><figcaption></figcaption></figure>

Pick the option that works best for you:

{% tabs %}
{% tab title="Flash" %}
If you have [Etcher](https://etcher.balena.io/) installed, you can just click the Flash button. This will automatically open Etcher with your image loaded. The contents of the image that gets loaded are the same as the contents of the image you would get from the **Download balenaOS** option. Once Etcher opens, proceed to [Provision device](#provision-device).

**This option is best for quickly flashing a device(s) in a single session. Once you close Etcher, the image will no longer be loaded in it.**
{% endtab %}

{% tab title="Download balenaOS" %}
This will download a zipped image file with a name like `balena-First-Fleet-imx8mm-var-som-6.10.24-v17.4.2.img.zip`. The contents of this image file are the same as what Etcher would have received if you had chosen the **Flash**. The difference is that you could reuse this image file repeatedly without having to fill out the form again.

**This option is best for preparing an image for provisioning several devices. Even if you close Etcher, you can just load the same image again for as many devices as you need, and they will all be provisioned with the same basic information that you indicated in the form.**
{% endtab %}

{% tab title="Download configuration file only" %}
This only downloads a configuration file with details that you filled out in the form and information about the fleet. **This is for more complex workflows and we do not recommend it for getting started**.

You can read more about it [here](https://github.com/balena-io/docs/blob/main/pages/reference/os/configuration/README.md).
{% endtab %}
{% endtabs %}

Once you have chosen one of the options, the button should update to whichever option you have chosen. Click the button and proceed.

## Provision device

Next, we will flash the downloaded image onto the device. To do so, follow the following steps:

* Insert the SD card to the host machine.
* Write the balenaOS file you downloaded to the SD card. We recommend using [Etcher](https://etcher.balena.io/).

![etcher flashing](/files/6uDePJiYOM1kcbJklXt4)

* Wait for writing of balenaOS to complete.
* Remove the SD card from the host machine.
* Insert the freshly flashed SD card into the Variscite VAR-SOM-MX8M-MINI Devkit.

![insert SD card](/files/wjiXzUcFxBN9RwoYEiwF)

* **Warning!** This will also completely erase internal storage medium, so please make a backup first.
* Set the BOOT-SELECT switch to EXT. Connect power to the Variscite VAR-SOM-MX8M-MINI Devkit.
* Wait for the Variscite VAR-SOM-MX8M-MINI Devkit to finish flashing and shutdown. Please wait until all LEDs are off.
* Remove the SD card from the Variscite VAR-SOM-MX8M-MINI Devkit.
* Set the BOOT-SELECT switch to INT.,Remove and re-connect power to the Variscite VAR-SOM-MX8M-MINI Devkit. to boot the device.

When complete, after a minute or two the device should appear on your balenaCloud [dashboard](https://dashboard.balena-cloud.com/), and you should now be ready to deploy some code. If you are not able get the device to appear on the dashboard, then check out our [troubleshooting guide for Variscite VAR-SOM-MX8M-MINI Devkit](https://github.com/balena-io/docs/blob/main/faq/troubleshooting/imx8mm-var-som/README.md) or try our [support channels](/learn/accounts/support-access).

## Install the balena CLI

Now that you have an `operational` device in your fleet, it's time to deploy some code. We will use the balena CLI for this. Follow the instructions below to install balenaCLI for the operating system available on your system. Skip the next part if you have balena CLI already installed.

{% tabs %}
{% tab title="OSX" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-macOS-x64-installer.pkg).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open the Terminal app ([Terminal User guide](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac)).
   {% endtab %}

{% tab title="Windows" %}

1. [Download the CLI installer](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-windows-x64-installer.exe).
2. Double click the downloaded file to run the installer and follow the installer's instructions.
3. To run balena CLI commands, open a command prompt: Click on the Windows Start Menu, type PowerShell, and then click on Windows PowerShell.
   {% endtab %}

{% tab title="Linux" %}

1. [Download the standalone CLI](https://github.com/balena-io/balena-cli/releases/download/v25.1.7/balena-cli-v25.1.7-linux-x64-standalone.tar.gz).
2. Extract the contents of the tar.gz file to any folder you choose, for example `/home/james`. The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena/bin`) to the PATH environment variable. Check this [StackOverflow](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) post for instructions. Close and re-open the terminal window so that the changes to PATH can take effect.
   {% endtab %}
   {% endtabs %}

After balena CLI is installed, login to your balena account using the `balena login` command on the terminal:

```shell
$ balena login
 _            _
| |__   __ _ | |  ____  _ __    __ _
| '_ \ / _` || | / __ \| '_ \  / _` |
| |_) | (_) || ||  ___/| | | || (_) |
|_.__/ \__,_||_| \____/|_| |_| \__,_|


Logging in to cloud.com
? How would you like to login? (Use arrow keys)
❯ Web authorization (recommended)
  Credentials
  Authentication token
  I don't have a balena account!
```

You will be asked to choose an authentication method, choose *Web authorization* which will bring up a web browser window that allows you to login to your balenaCloud account. Click the **Authorize** button, and head back to the terminal after the login successful message appears.

<figure><img src="/files/r3sbRVFEW8QblyCuJJBK" alt="Web authorization" width="563"><figcaption></figcaption></figure>

## Create a release

After login, test the balena CLI by running the `balena fleet list` command, which should return information about the fleet you created in the previous step. Take a note of the fleet `NAME` as you'll need this in the next step to push the code to your device(s) in that fleet.

```shell
$ balena fleets
ID    NAME         SLUG                                 DEVICE TYPE           DEVICE COUNT   ONLINE DEVICES
98264 First-Fleet  balena CLI/first-fleet    Variscite VAR-SOM-MX8M-MINI Devkit    0              0
```

{% tabs %}
{% tab title="Node.js" %}
A nice project to try is the [balena-nodejs-hello-world](https://github.com/balena-io-examples/balena-nodejs-hello-world) project. It's a Node.js web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-nodejs-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Python" %}
A nice project to try is the [balena-python-hello-world](https://github.com/balena-io-examples/balena-python-hello-world) project. It's a Python web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-python-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="C++" %}
A nice project to try is the [balena-cpp-hello-world](https://github.com/balena-io-examples/balena-cpp-hello-world) project. It's a C++ web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-cpp-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Rust" %}
A nice project to try is the [balena-rust-hello-world](https://github.com/balena-io-examples/balena-rust-hello-world) project. It's a Rust web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-rust-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}

{% tab title="Go" %}
A nice project to try is the [balena-go-hello-world](https://github.com/balena-io-examples/balena-go-hello-world) project. It's a Go web server that serves a static page on port 80. To get started, [download the project](https://github.com/balena-io-examples/balena-go-hello-world/archive/master.zip) as a zipped file from GitHub, unzip it and open a terminal in the root of the extracted project directory.
{% endtab %}
{% endtabs %}

To create a release, use the `balena push First-Fleet` command replacing `First-Fleet` with the name of your fleet. Ensure you are working from the root of the extracted project directory.

```shell
$ balena push First-Fleet
```

This command pushes the code to the balena builders, where it will be compiled, built, turned into a release, and applied to every device in the fleet.

You'll know your code has been successfully compiled and built when our friendly unicorn mascot appears in your terminal:

```shell
[hello-world]  Successfully built 51bd190f7530
[Info]       Generating image deltas from release 8acfdc579f7cb0fe424d1b800588b6f5 (id: 2186018)
[Success]    Successfully generated image deltas
[Info]       Uploading images
[Success]    Successfully uploaded images
[Info]       Built on builder05
[Success]    Release successfully created!
[Info]       Release: c0c593803588a304c173124827d96b99 (id: 2186339)
[Info]       ┌────────────────────┬────────────┬────────────┐
[Info]       │ Service            │ Image Size │ Build Time │
[Info]       ├────────────────────┼────────────┼────────────┤
[Info]       │ hello-world        │ 190.04 MB  │ 50 seconds │
[Info]       └────────────────────┴────────────┴────────────┘
[Info]       Build finished in 1 minutes, 4 seconds
                            \
                             \
                              \\
                               \\
                                >\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    > /
                             j    < _\
                         _.-' :      ``.
                         \ r=._\        `.
                        <`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        >\  >
                                    ,.-' >.'
                                   <.'_.''
                                     <'
```

The release will then be downloaded and started by all the devices in the fleet. You can see the progress of the device code updates on the device dashboard:

<figure><img src="/files/RympfKs2cwoxUeRtMC6R" alt="Service download progress"><figcaption></figcaption></figure>

After the download, you should now have a web server running on your device and see some logs on your dashboard.

To give your device a public URL, click the *Public Device URL* toggle on the device dashboard. Public device URL allow you to serve content from the device to the world easily without configuration as long as the server is running on port 80.

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt="Enable public URLs" width="563"><figcaption></figcaption></figure>

Follow the URL to view the welcome page with additional resources. Alternatively, you can point your browser to your device's local IP address to access the server running on your device. You can find the device's IP address on the device dashboard page. This is what you should be seeing.

<figure><img src="/files/1dEQwLOZUA2Zpdyc75VU" alt="Success screen 1" width="563"><figcaption></figcaption></figure>

## Developing your project

Now, let's try making some changes to this project and testing them right on the device. The project can be modified and pushed again using the same method as above, but since we are using a development version of the OS, we can enable *Local mode* and push directly to the device for a faster development cycle.

Activate local mode on the device via the dashboard.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt="Enable Local Mode" width="563"><figcaption></figcaption></figure>

Once enabled, you can now use `balena push` again, but this time we will push directly to the local IP address of the device obtained via the dashboard.

<figure><img src="/files/Z0yEItwiOVbuWq5LRlT5" alt="Local IP address" width="563"><figcaption></figcaption></figure>

```shell
$ balena push 10.19.0.153
```

The same build process as before is carried out, but this time instead of using the balena builders, the build takes place locally on the device itself.

```shell
[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [8/26/2021, 11:58:18 AM] Creating network 'default'
[Logs]    [8/26/2021, 11:58:19 AM] Installing service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Installed service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:20 AM] Starting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:23 AM] Started service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:58:24 AM] [hello-world] Starting server on port 80
[Live]    Device state settled
```

The balena CLI will now watch for changes to all the files within the project, and automatically push changes to the device when detected. Let's try making a change to title of our balena welcome page. Navigate to the `index.html` file present in the `static` directory of the project. Open the file and change the title from `Welcome to balena!` to `Hello balena!` and save the file. After saving the changes, you can observe balena CLI automatically start rebuilding only the parts of the Dockerfile that has been changed.

```shell
[Live]    Detected changes for container hello-world, updating...

...
[Live]    [hello-world] Restarting service...
[Logs]    [8/26/2021, 11:59:01 AM, 2:42:32 AM] Service exited 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:04 AM, 2:42:35 AM] Restarting service 'hello-world sha256:...'
[Logs]    [8/26/2021, 11:59:05 AM, 2:42:36 AM] [hello-world] Starting server on port 80
```

When the rebuild is complete, take a look at the public device URL again to see your changes. The welcome page should have been updated with the new title.

<figure><img src="/files/RDB35NRe15zGLKZKqwWk" alt="Success screen 2" width="563"><figcaption></figcaption></figure>

## Next steps

Once you've finished making your changes, disable local mode and the device will revert back to running the latest release that's on your fleet. To update your fleet with the latest changes you've just worked on, use `balena push <fleet name>` once more to create a new release with those changes.

When it's finished building the device(s) will update as before. Remember anything pushed to the fleet in this way can be applied to 10+ or 1000+ devices with no extra effort! To continue learning, explore parts of the guide in more detail:

* Learn more about [local mode](/learn/develop/local-mode), which allows you to build and sync code to your device locally for rapid development.
* Develop an application with [multiple containers](/learn/develop/multicontainer) to provide a more modular approach to fleet management.
* Manage your device fleet with the use of [configuration](/learn/manage/configuration), [environment](/learn/manage/variables), and [service variables](/learn/manage/variables).
* Find out more about the [balena CLI](https://github.com/balena-io/docs/blob/main/pages/reference/balena-cli.md) and the functionality it offers.
* Visit our blog to find step-by-step tutorials for some [classic balena projects](https://blog.balena.io/tags/project).
* To publish what you will build or have already built, head over to [balenaHub](https://hub.balena.io/).
* If you find yourself stuck or confused, help is just a [click away](https://www.balena.io/support).

**Enjoy balenafying all the things!**


# Develop


# Develop locally

Local mode is the development mode for balena. It allows you to build and sync code to a single development device in your local network without having to go through the balenaCloud build service and deployment pipeline. It uses the Docker daemon on the device to build container images, and then the device Supervisor starts the containers in the same way as if they were deployed via the cloud.

## Local mode requirements

To use local mode on a device:

* The device must be running balenaOS v2.29.0 or higher.
* The device must be running a [development](/reference/os/overview) variant of the OS.
* You must have the [balena CLI](/reference/balena-cli/latest) installed on your development machine.
* Local mode must be enabled through the balenaCloud dashboard. You can enable it from the device *Settings* tab.

<figure><img src="/files/xjR9gJs2DjivYWeWproP" alt=""><figcaption></figcaption></figure>

## Local mode caveats

* In local mode, a device will not send logs back to the balenaCloud dashboard. Refer to the [local mode logs section](#local-mode-logs) to view logs in local mode.
* Device and service environment variables set from the balenaCloud will not be applied to local mode containers. It is still possible to set environment variables in your `docker-compose.yml` or `Dockerfile`.
* Changes to device [configuration](/learn/manage/configuration), for example, `BALENA_HOST_CONFIG_gpu_mem`, will result in the device rebooting and applying those settings.
* Actions such as *Restart services* and *Purge data* will not apply to local mode containers.
* When switching out of local mode and back to tracking releases from balenaCloud, the Supervisor will destroy any local mode containers and volumes, as well as clean up unneeded base images, and then start the release that balenaCloud instructs it to run.

<figure><img src="/files/vRUKUIK97p3lL2oCVn8N" alt=""><figcaption></figcaption></figure>

## Scan the network and find your device

Before you can get your app running on your device in local mode, you have to find your device. You can find the `short-uuid` and local IP address of the device from the device dashboard or by scanning the network. To perform a scan, login to the balena CLI and use `balena device detect` to find any local balenaOS devices. All balenaOS devices advertise themselves on the network using [Avahi](https://linux.die.net/man/8/avahi-daemon). The names take the form `<short-uuid>.local`, where the `short-uuid` is the UUID you see on your device dashboard.

{% hint style="warning" %}
You may need administrator privileges to run `balena device detect` as it requires access to all network interfaces.
{% endhint %}

**Command**

```bash
sudo balena device detect
```

**Output**

```bash
Reporting scan results
-
  host:          63ec46c.local
  address:       192.168.86.45
  dockerInfo:
    Containers:        1
    ContainersRunning: 1
    ContainersPaused:  0
    ContainersStopped: 0
    Images:            4
    Driver:            aufs
    SystemTime:        2020-01-09T21:17:11.703029598Z
    KernelVersion:     4.19.71
    OperatingSystem:   balenaOS 2.43.0+rev1
    Architecture:      armv7l
  dockerVersion:
    Version:    18.09.8-dev
    ApiVersion: 1.39

```

## Push over a new project

When local mode has been activated, balena CLI can push code directly to the local device instead of going via the balenaCloud builders. As code is built on the device and then executed, this can significantly speed up development when requiring frequent changes. To do this, we use the `balena push` command providing either the local IP address or `<short-uuid>.local`, obtained from the preceding `balena device detect` command.

{% hint style="info" %}
By default `balena push` will build from the current working directory, but it is also possible to specify the project directory via the `--source` option.
{% endhint %}

Once the code has been built on the device, it immediately starts executing, and logs are output to the console. At any time, you can disconnect from the local device by using `Ctrl-C`. Note that after disconnection, the services on the device will continue to run.

**Command**

```bash
balena push 63ec46c.local
```

**Output**

```bash
[Info]    Starting build on device 63ec46c.local
[Info]    Creating default composition with source: .
[Build]   [main] Step 1/9 : FROM balenalib/raspberrypi3-node:10-stretch-run
[Build]   [main]  ---> 383e163cf46d
[Build]   [main] Step 2/9 : WORKDIR /usr/src/app
[Build]   [main]  ---> Running in 9d8460cb9d11
[Build]   [main] Removing intermediate container 9d8460cb9d11
[Build]   [main]  ---> 143557c3351a
[Build]   [main] Step 3/9 : COPY package.json package.json
[Build]   [main]  ---> 5a5818881215
[Build]   [main] Step 4/9 : RUN JOBS=MAX npm install --production --unsafe-perm && npm cache verify && rm -rf /tmp/*
[Build]   [main]  ---> Running in 03a4e27048cc
[Build]   [main]
[Build]   > ejs@3.0.1 postinstall /usr/src/app/node_modules/ejs
[Build]   > node ./postinstall.js
[Build]   [main] Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)
[Build]   [main] npm
[Build]   [main] notice created a lockfile as package-lock.json. You should commit this file.
[Build]
[Build]   [main] added 51 packages from 38 contributors and audited 127 packages in 9.334s
[Build]   [main] found 0 vulnerabilities
[Build]   [main] Cache verified and compressed (~/.npm/_cacache):
[Build]   [main] Content verified: 102 (1362229 bytes)
[Build]   [main] Index entries: 155
[Build]   [main] Finished in 1.568s
[Build]   [main] Removing intermediate container 03a4e27048cc
[Build]   [main]  ---> e199dbb1fe73
[Build]   [main] Step 5/9 : COPY . ./
[Build]   [main]  ---> 3309e8315a64
[Build]   [main] Step 6/9 : ENV UDEV=1
[Build]   [main]  ---> Running in 0867fd67e166
[Build]   [main] Removing intermediate container 0867fd67e166
[Build]   [main]  ---> cdb9c9a629df
[Build]   [main] Step 7/9 : CMD ["npm", "start"]
[Build]   [main]  ---> Running in b5e4aa98c5ab
[Build]   [main] Removing intermediate container b5e4aa98c5ab
[Build]   [main]  ---> 7b4a59f62bb5
[Build]   [main] Step 8/9 : LABEL io.resin.local.image=1
[Build]   [main]  ---> Running in 9d50c18f946c
[Build]   [main] Removing intermediate container 9d50c18f946c
[Build]   [main]  ---> 38935745a619
[Build]   [main] Step 9/9 : LABEL io.resin.local.service=main
[Build]   [main]  ---> Running in 5d8e9f324e28
[Build]   [main] Removing intermediate container 5d8e9f324e28
[Build]   [main]  ---> 88065a1a3f00
[Build]   [main] Successfully built 88065a1a3f00
[Build]   [main] Successfully tagged local_image_main:latest

[Info]    Streaming device logs...
[Live]    Watching for file changes...
[Live]    Waiting for device state to settle...
[Logs]    [1/9/2020, 1:46:58 PM] Creating network 'default'
[Logs]    [1/9/2020, 1:46:58 PM] Creating volume 'resin-data'
[Logs]    [1/9/2020, 1:46:58 PM] Installing service 'main sha256:88065a1a3f002ff7eaf6c56b5c8bdb477c43437d41fcbb3ec683842c86b25432'
[Logs]    [1/9/2020, 1:46:59 PM] Installed service 'main sha256:88065a1a3f002ff7eaf6c56b5c8bdb477c43437d41fcbb3ec683842c86b25432'
[Logs]    [1/9/2020, 1:46:59 PM] Starting service 'main sha256:88065a1a3f002ff7eaf6c56b5c8bdb477c43437d41fcbb3ec683842c86b25432'
[Logs]    [1/9/2020, 1:47:01 PM] Started service 'main sha256:88065a1a3f002ff7eaf6c56b5c8bdb477c43437d41fcbb3ec683842c86b25432'
[Logs]    [1/9/2020, 1:47:03 PM] [main]
[Live]    Device state settled
[Logs]    [1/9/2020, 1:47:03 PM] [main] > simple-server-node@1.0.0 start /usr/src/app
[Logs]    [1/9/2020, 1:47:03 PM] [main] > node server.js
[Logs]    [1/9/2020, 1:47:03 PM] [main]
[Logs]    [1/9/2020, 1:47:04 PM] [main] Example app listening on port  80
```

### Livepush

Local mode also has another huge benefit, known as [Livepush](https://github.com/balena-io-modules/livepush). Livepush makes intelligent decisions on how, or even if, to rebuild an image when changes are made. Instead of creating a new image and container with every code change, the Dockerfile commands are executed from within the running container. This means that, for example, if you added a dependency to your `package.json`, rather than having to install all of the dependencies again, only the new dependency would be installed.

When a source file is modified, the Supervisor will immediately detect the change and then either rebuild the image or, for source files that run in-service, replace the changed files in situ in the relevant container layer and restart the service. As this happens in a few seconds, it makes the process of developing much faster and more convenient.

```bash
[Live]    Detected changes for container main, updating...
[Live]    [main] Restarting service..
```

{% hint style="info" %}
You can disable Livepush by passing the `--nolive` option to `balena push`. In this case to rebuild on the device you will need to perform another `balena push`.
{% endhint %}

### Local mode logs

By default, when pushing code to a device in local mode using the balena CLI, the logs will be output to the console. You can prevent this by passing the `--detached` (`-d`) option to the `balena push` command (you may also detach the console at any time by pressing `Ctrl-C`).

```bash
balena push 63ec46c.local --detached
```

When detached, the services continue to run on the device, and you can access the logs using the `balena device logs` command, again passing the local IP address or `<short-uuid>.local`.

```shell
balena device logs 63ec46c.local
```

This command will output logs for the system and all running services. You may optionally filter the output to include only system or specific service logs using the available `--system` (`-S`) and `--service` (`-s`) options. For example, to output only the system logs:

```bash
balena device logs 63ec46c.local --system
```

To filter logs by a service, use the `--service` option. You may specify this option multiple times to output logs from multiple services.

```bash
balena device logs 63ec46c.local --service main
balena device logs 63ec46c.local --service first --service second
```

These options can be combined to output system and selected service logs e.g.

```bash
balena device logs 827b231.local --system --service first --service second
```

{% hint style="info" %}
You may also specify the `--service` and `--system` options using the `balena push` command to filter the log output.
{% endhint %}

## SSH into the running app container or host OS

To access the local device over [SSH](/learn/manage/ssh-access), use the `balena device ssh` command specifying the device IP address or `<short-uuid>.local`. By default, SSH access is routed into the host OS shell and, from there, we can check system logs and [perform other troubleshooting tasks](/learn/manage/ssh-access#troubleshooting-with-host-os-access):

```bash
balena device ssh 192.168.86.45
```

To connect to a container, we can specify the service name e.g.

```bash
sudo balena device ssh 63ec46c.local my-service
```

{% hint style="info" %}
If an IP address or a `.local` hostname is used (instead of a fleet name or device UUID), `balena device ssh` establishes a direct connection to the device on port `22222` that does not rely on cloudlink.
{% endhint %}

## Using a Private Docker Registry

If your project relies on a private base image, then it is possible to specify your registry credentials when doing a `balena push` by passing the `--registry-secrets` option, as shown below.

```bash
balena push 192.168.86.45 --registry-secrets /Path/To/File/dockerhub-secret.yml
```

Where `dockerhub-secret.yml` is a YAML file containing my private registry usernames and passwords to be used by the device balenaEngine when pulling base images during a build.

Sample secrets YAML file:

```yaml
'https://index.docker.io/v2/':
  username: johnDoe
  password: myPassword
```


# Define a container

Balena uses [Docker](https://www.docker.com/) containers to manage deployment and updates. You can use one or more containers to package your services with whichever environments and tools they need to run.

To ensure a service has everything it needs, you'll want to create a list of instructions for building a [container image](https://docs.docker.com/engine/understanding-docker/#/inside-docker). Whether the build process is done [on your device](/learn/develop/local-mode), [on your workstation](/reference/balena-cli/latest#build), or on the [balena builders](/learn/deploy/deployment), the end result is a read-only image that ends up on your device. This image is used by the container engine (balena or Docker, depending on the balenaOS version) to kick off a running container.

{% hint style="info" %}
For additional information on working with Dockerfiles with balena see the [services masterclass](/learn/more/masterclasses/services-masterclass).
{% endhint %}

## Dockerfiles

The instructions for building a container image are written in a [Dockerfile](https://docs.docker.com/engine/reference/builder/) - this is similar to a `Makefile` in that it contains a recipe or set of instructions to build our container.

The syntax of Dockerfiles is fairly simple - at core there are 2 valid entries in a Dockerfile - comments, prepended with `#` as in script files, and instructions of the format `INSTRUCTION arguments`.

Typically you will only need to use 4 instructions - [FROM](https://docs.docker.com/engine/reference/builder/#from), [RUN](https://docs.docker.com/engine/reference/builder/#run) and [ADD](https://docs.docker.com/engine/reference/builder/#add) or [COPY](https://docs.docker.com/engine/reference/builder/#copy):-

* [FROM](https://docs.docker.com/engine/reference/builder/#from) **has** to be the first instruction in any valid `Dockerfile` and defines the base image to use as the basis for the container you're building.
* [RUN](https://docs.docker.com/engine/reference/builder/#run) simply executes commands in the container - this can be of the format of a single line to execute, e.g. `RUN apt-get -y update` which will be run via `/bin/sh -c`, or `[ "executable", "param1", "param2", ... ]` which is executed directly.
* [ADD](https://docs.docker.com/engine/reference/builder/#add) copies files from the current directory into the container, e.g. `ADD <src> <dest>`. Note that if `<dest>` doesn't exist, it will be created for you, e.g. if you specify a folder. If the `<src>` is a *local* tar archive it will unpack it for you. It also allows the `<src>` to be a url but will **not** unpack *remote* urls.
* [COPY](https://docs.docker.com/engine/reference/builder/#copy) is very similar to [ADD](https://docs.docker.com/engine/reference/builder/#add), but without the compression and url functionality. According to [the Dockerfile best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy), you should always use [COPY](https://docs.docker.com/engine/reference/builder/#copy) unless the auto-extraction capability of [ADD](https://docs.docker.com/engine/reference/builder/#add) is needed.
* [CMD](https://docs.docker.com/engine/reference/builder/#cmd) this command provides defaults for an executing container. This command will be run when the container starts up on your device, whereas RUN commands will be executed on our build servers. In a balena service, this is typically used to execute a start script or entrypoint for the user's service. [CMD](https://docs.docker.com/engine/reference/builder/#cmd) should always be the last command in your Dockerfile. The only processes that will run inside the container are the [CMD](https://docs.docker.com/engine/reference/builder/#cmd) command and all processes that it spawns.

For details on other instructions, consult the official [Dockerfile documentation](https://docs.docker.com/engine/reference/builder/).

### Using Dockerfiles with balena

{% hint style="danger" %}
Containers ran as single container **have no security restrictions**, this should only be used for prototyping and testing. For production applications, we recommend defining your own `docker-compose.yml` file with the appropriate security settings for your use case. For more information on this, see our [multicontainer documentation](/learn/develop/multicontainer).
{% endhint %}

To deploy a single-container release to balena, simply place a `Dockerfile` at the root of your repository. A `docker-compose.yml` file will be automatically generated, ensuring your container has host networking, is privileged, and has `lib/modules`, `/lib/firmware`, and `/run/dbus` bind mounted into the container. The default `docker-compose.yml` will look something like this:

{% hint style="warning" %}
If you have devices in your app that have a supervisor version lower than 7.22.0, then you should use the `io.resin.features.` form of the labels to ensure that all devices obey the label. Earlier supervisor versions will not understand the `io.balena.features` label.
{% endhint %}

```yaml
version: '2.1'
networks: {}
volumes:
  resin-data: {}
services:
  main:
    build:
      context: .
    privileged: true
    restart: always
    network_mode: host
    volumes:
      - 'resin-data:/data'
    labels:
      io.balena.features.kernel-modules: '1'
      io.balena.features.firmware: '1'
      io.balena.features.dbus: '1'
      io.balena.features.supervisor-api: '1'
      io.balena.features.balena-api: '1'
```

Releases with multiple services should include a `Dockerfile` or `package.json` in each service directory. A `docker-compose.yml` file will need to be defined at the root of the repository, as discussed in our [multicontainer documentation](/learn/develop/multicontainer).

You can also include a `.dockerignore` file with your project if you wish the builder to ignore certain files.

{% hint style="warning" %}
You *don't* need to worry about ignoring `.git` as the builders already do this by default.
{% endhint %}

## Dockerfile templates

Dockerfile templates are a balena-specific feature that allow our builders to substitute a value for one of the following variables at build time:

| Variable Name         | Description                                                                                                                                                                                                                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BALENA\_APP\_NAME     | The name of the fleet.                                                                                                                                                                                                                                                          |
| BALENA\_ARCH          | The instruction set architecture for the base images associated with this device.                                                                                                                                                                                               |
| BALENA\_MACHINE\_NAME | The name of the yocto machine this board is base on. It is the name that you will see in most of the balena [Docker base images](/reference/base-images/balena-base-images). This name helps us identify a specific [BSP](https://en.wikipedia.org/wiki/Board_support_package). |
| BALENA\_RELEASE\_HASH | The hash corresponding to the release.                                                                                                                                                                                                                                          |
| BALENA\_SERVICE\_NAME | The name of the service defined in the `docker-compose.yml` file.                                                                                                                                                                                                               |

The original purpose of these templates was to allow our builders to build containers for multiple architectures from one code repository when using the deprecated balenalib base images. For new projects, we recommend using standard Dockerfiles and either specifying the architecture in your FROM line, or utilizing base images that are published with the [multi-platform feature](https://docs.docker.com/build/building/multi-platform/). For example:

`FROM bh.cr/balenalabs/browser-aarch64`

Here, we are pulling an ARMv8 (aarch64) architecture-specific container image. This image can only be used for fleets with devices of that architecture.

`FROM debian:trixie`

This Debian Official Docker image is a multi-arch image instead. Upon build time, the balena builders would pull the correct architecture of the image based on the default device type of your fleet. This reduces complexity and provides a similar feature set to Dockerfile templates in the past.

It is possible to have different device types in the same fleet, as long as they have the same or compatible architectures. You need to ensure that your packages and modules are also available in that target architecture, otherwise, your application might throw errors or fail during runtime.

If you are still using balenalib base images for an existing project, you can use dockerfile templates as described below:

```dockerfile
FROM {{ $names.base_images.lib }}/%%BALENA_MACHINE_NAME%%-node

COPY package.json /package.json
RUN npm install

COPY src/ /usr/src/app
CMD ["node", "/usr/src/app/main.js"]
```

This `dockerfile.template` file will build and deploy a Node.js project for any of the devices supported by balena, regardless of device architecture, whether is [ARM](https://en.wikipedia.org/wiki/ARM_architecture) or [x86](https://en.wikipedia.org/wiki/X86).

In this example, the build variable `%%BALENA_MACHINE_NAME%%`. This will be replaced by the machine name (i.e.: `raspberry-pi`) at build time. Refer to [supported machine names and architectures](/reference/hardware/devices).

The machine name is inferred from the device type of the fleet you are deploying on. So if you have a NanoPi Neo Air fleet, the machine name will be `nanopi-neo-air` and an `armv7hf` architecture base image will be built.

{% hint style="warning" %}
If your fleet contains devices of different types, the `%%BALENA_MACHINE_NAME%%` build variable **will not** evaluate correctly for all devices. Your fleet services are built once for all devices, and the `%%BALENA_MACHINE_NAME%%` variable will pull from the device type associated with the fleet, rather than the target device. In this scenario, you can use `%%BALENA_ARCH%%` to pull a base image that matches the shared architecture of the devices in your fleet.
{% endhint %}

If you want to see an example of build variables in action, have a look at this [basic openssh example](https://github.com/balena-io-playground/balena-openssh).

## Multiple Dockerfiles

There are cases when you would need a higher granularity of control when specifying build instructions for different devices and architectures than a single Dockerfile template can provide. An example of this would be when different configuration or installation files are required for each architecture or device.

When creating a release, the balenaCloud build servers or the balena CLI tool (depending on the deployment method used) look at all available Dockerfiles and build the appropriate image using the following order of preference:

* Dockerfile.\<device-type>
* Dockerfile.\<arch>
* Dockerfile.template

As an example, let's say you have two Dockerfiles available, `Dockerfile.raspberrypi3` and `Dockerfile.template`. Whenever you publish the application to balenaCloud, if the fleet `device-type` is Raspberry Pi 3, `Dockerfile.raspberrypi3` will be selected as an exact match and for all other devices the builder will automatically select `Dockerfile.template`.

Note that this feature works with the following commands: `git push`, `balena push`, `balena build`, and `balena deploy`.

## Node applications

Balena supports [Node.js](https://nodejs.org/) natively using the [package.json](https://docs.npmjs.com/files/package.json) file located in the root of the repository to determine how to build and execute node applications.

When you push your code to your fleet, the build server generates a [container](https://en.wikipedia.org/wiki/Operating_system%E2%80%93level_virtualization) for the environment your device operates in, deploys your code to it and runs `npm install` to resolve [npm](https://www.npmjs.org/) dependencies, reporting progress to your terminal as it goes.

If the build executes successfully the release is deployed to your device where the supervisor runs it in place of any previously running containers, using `npm start` to execute your code (note that if no start script is specified, it defaults to running `node server.js`.)

### Node.js Example

A good example of this is the [text-to-speech](https://github.com/balena-io/text2speech) application - here's its `package.json` file\*:

```json
{
	"name": "text2speech",
	"description": "Simple balena app that uses Google's TTS endpoint",
	"repository": {
		"type": "git",
		"url": "https://github.com/balena-io/text2speech.git"
	},
	"scripts": {
		"preinstall": "bash deps.sh"
	},
	"version": "0.0.3",
	"dependencies": {
		"speaker": "~0.0.10",
		"request": "~2.22.0",
		"lame": "~1.0.2"
	},
	"engines": {
		"node": "0.10.22"
	}
}
```

{% hint style="warning" %}
We don't specify a `start` script here which means node will default to running `server.js`. We execute a bash script called `deps.sh` before `npm install` tries to satisfy the code's dependencies. Let's have a look at that:-
{% endhint %}

```shell
apt-get install -y alsa-utils libasound2-dev
mv sound_start /usr/bin/sound_start
```

These are shell commands that are run within the container on the build server which are configured such that dependencies are resolved for the target architecture not the build server's - this can be very useful for deploying non-javascript code or fulfilling package dependencies that your node code might require.

We use [Raspbian](https://www.raspbian.org/) as our contained operating system, so this script uses [aptitude](https://wiki.debian.org/Aptitude) to install native packages before moving a script for our node code to use over to `/usr/bin` (the install scripts runs with root privileges within the container.)

{% hint style="warning" %}
With a plain Node.js project, our build server will detect compatible nodejs versions from the `package.json` and build the container using a Docker image that satisfies the version requirement. If no version is specified then the default node version is `0.10.22` and it will be used if a node version is not specified. There will be an error if the specified node version is not in our registry. You can either try another node version or contact us to be supported. More details about Docker node images in our registry can be found [here](/reference/base-images/balena-base-images).
{% endhint %}

<figure><img src="/files/LbnlnMMO7afFqHTnsi5h" alt=""><figcaption></figcaption></figure>

## Container Requirements

The balena Supervisor requires that the directory `/tmp/balena` in containers be available for inter-container communication via [update locks](/learn/deploy/release-strategy/update-locking). Therefore, scripts should not attempt to remove this directory on startup.


# Multiple containers

As your apps grow more complex, you may find significant benefit in running some services in separate containers. Splitting your app into multiple containers allows you to better isolate and maintain key services, providing a more modular and secure approach to fleet management. Each service can be packaged with the operating environment and tools it specifically needs to run, and each service can be limited to the minimum system resources necessary to perform its task. The benefits of multicontainer fleets compound as the complexity of the app grows. With multicontainer, each service is updated independently. Hence, larger apps can be developed and maintained by separate teams, each free to work in a way that best supports their service.

{% hint style="info" %}
For additional information on working with multiple containers with balena see the [services masterclass](/learn/more/masterclasses/services-masterclass).
{% endhint %}

This guide will cover the considerations you need to take into account when running multiple containers, including `docker-compose.yml` configuration and some important balena specific settings.

## docker-compose.yml file

The multicontainer functionality provided by balena is built around the [**Docker Compose**](https://docs.docker.com/compose/overview/) file format. The balena device supervisor implements a subset of the [Compose v2.1 feature set](https://docs.docker.com/compose/compose-file/compose-file-v2/). You can find a full list of supported and known unsupported features in our [device supervisor reference docs](/reference/supervisor/docker-compose).

At the root of your multicontainer release, you'll use a `docker-compose.yml` file to specify the configuration of your containers. The `docker-compose.yml` defines the services you'll be building, as well as how the services interact with each other and the host OS.

Here's an example `docker-compose.yml` for a [simple multicontainer release](https://github.com/balenalabs/multicontainer-getting-started), composed of a static site server, a websocket server, and a proxy:

```yaml
version: '2'
services:
  frontend:
    build: ./frontend
    restart: always
    expose:
      - '80'
  proxy:
    build: ./haproxy
    depends_on:
      - frontend
      - data
    ports:
      - '80:80'
  data:
    build: ./data
    expose:
      - '8080'
```

Each service can either be built from a directory containing a `Dockerfile`, as shown here, or can use a **Docker** image that has already been built, by replacing `build:` with `image:`. If your containers need to be started in a specific order, make sure to use the `depends_on:` [setting](https://docs.docker.com/compose/compose-file/compose-file-v2/#depends_on).

{% hint style="warning" %}
Note that `depends_on` only controls the startup order and will not restart services if a dependency restarts. Also if a service is expected to stop after performing some actions, do not include it as a dependency or the service that depends on it may not start.
{% endhint %}

Unlike single container fleets, multicontainer fleets do not run containers in privileged mode by default. If you want to make use of hardware, you will either have to set some services to privileged, using `privileged: true`, or use the `cap_add` and `devices` settings to map in the correct hardware access to the container.

Also, in a balena device, unlike with regular docker compose, containers restart by default if their process crashes or the device is restarted. This behavior can be changed by setting the restart policy to one of the [values supported by the engine](https://docs.docker.com/compose/compose-file/compose-file-v2/#restart) (the default is `restart: always`).

As an example, here the `gpio` service is set up to use i2c and serial uart sensors and a restart policy of `on-failure`.

```dockerfile
gpio:
    build: ./gpio
    devices:
      - "/dev/i2c-1:/dev/i2c-1"
      - "/dev/mem:/dev/mem"
      - "/dev/ttyACM0:/dev/ttyACM0"
    cap_add:
      - SYS_RAWIO
    restart: on-failure
```

## Balena settings

There are a few settings and considerations specific to balena that need to be taken into account when building multicontainer fleets.

### Network mode

Setting `network_mode` to `host` allows the container to share the same network namespace as the host OS. When this is set, any ports exposed on the container will be exposed locally on the device. This is necessary for features such as bluetooth.

### Named volumes

With multicontainer fleets, balena supports the use of named volumes, a feature that expands on the [persistent storage](/learn/develop/runtime#persistent-storage) functionality used by older versions of balenaOS. Named volumes can be given arbitrary names and can be linked to a directory in one or more containers. As long as every release of the fleet includes a `docker-compose.yml` and the volume name does not change, the data in the volume will persist across updates.

Use the `volumes` field of the service to link a directory in your container to your named volume. The named volume should also be specified at the top level of the `docker-compose.yml`:

```yaml
version: '2'
volumes:
  resin-data:
services:
  example:
    build: ./example
    volumes:
      - 'resin-data:/data'
```

For devices upgraded from older versions of balenaOS to v2.12.0 or higher, a link will automatically be created from the `/data` directory of the container to the `resin-data` named volume (similar to above). This ensures fleet behavior will remain consistent across host OS versions. One notable difference is that accessing this data via the host OS is done at `/var/lib/docker/volumes/<FLEET ID>_resin-data/_data`, rather than the `/mnt/data/resin-data/<FLEET ID>` location used with earlier host OS versions.

balena does not support the use of bind mounts at this time, aside from the ones which are provided by [feature labels](#labels).

### Core dumps for containers

BalenaOS v2.113.31 and later, by default, will not generate core dump files when a container crashes. This prevents a buggy container that is crash looping to fill up all available storage space on a device.

[Core dumps](https://en.wikipedia.org/wiki/Core_dump) are files with the contents of the memory used by a process at the time it crashes. They are a relatively advanced troubleshooting tool, particularly useful for low-level debugging of programs written in languages that compile to native code. For example, a tool like the `gdb` debugger can read a core dump and provide a stack trace showing the sequence of functions calls that led to the crash.

If you need core dumps, you can easily enable them by editing your `docker-compose.yml` and setting `ulimits.core: -1` for the desired services. For example:

```yaml
version: '2'
services:
  example:
    ulimits:
      core: -1
```

### Labels

In addition to the settings above, there are some balena specific labels that can be defined in the `docker-compose.yml` file. These provide access to certain bind mounts and environment variables without requiring you to run the container as privileged. You can a detailed list of these labels on the [docker-compose.yml fields page](/reference/supervisor/docker-compose#labels).

### Container requirements

An additional set of labels ensures device compatibility for running a service. For example, before updating to a new release, it may be desirable to ensure that the device is running a specific version of [Supervisor](/reference/supervisor/supervisor-api) or has a specific version of the [NVIDIA Tegra Linux Driver Package](https://developer.nvidia.com/embedded/linux-tegra) (L4T).

The following set of requirement labels are enforced via the supervisor. Each service may define one or more requirements and if any of them is not met for any non-[optional](#optional-containers) service, then [the release will be rejected](/learn/manage/device-statuses#update-statuses) and no changes will be performed for the new release.

| Label                                       | Description                                                                                                                             | Valid from Supervisor | Valid from CLI         |
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ---------------------- |
| io.balena.features.requires.sw\.supervisor  | Device Supervisor version (specified as a [version range](https://www.npmjs.com/package/semver))                                        | 10.16.17              | All supported versions |
| io.balena.features.requires.sw\.l4t         | [L4T](https://developer.nvidia.com/embedded/linux-tegra) version (specified as a [version range](https://www.npmjs.com/package/semver)) | 10.16.17              | All supported versions |
| io.balena.features.requires.hw\.device-type | The [device type](/reference/hardware/devices) as given by `BALENA_MACHINE_NAME`                                                        | 11.1.0                | All supported versions |
| io.balena.features.requires.arch.sw         | The [architecture](/reference/base-images/balena-base-images) as given by `BALENA_ARCH`                                                 | 14.10.11              | All supported versions |
| io.balena.features.requires.sw\.balena-os   | balenaOS version (specified as a [version range](https://www.npmjs.com/package/semver))                                                 | 17.4.2                | 25.0.0                 |
| io.balena.features.requires.sw\.linux       | Linux kernel version (specified as a [version range](https://www.npmjs.com/package/semver))                                             | 17.4.2                | 25.0.0                 |

For example, the following composition defines requirements on the supervisor and l4t version on the first service, and on the device type and architecture on the second service.

```yaml
version: '2'
services:
  first-service:
    build: ./first-service
    labels:
      io.balena.features.requires.sw.supervisor: '>=14'
      io.balena.features.requires.sw.l4t: '>=32.2.0'
  second-service:
    image: my-second-image
    labels:
      io.balena.features.requires.hw.device-type: 'jetson-nano'
      io.balena.features.requires.arch.sw: 'aarch64'
```

Here's an example of how to specify an OS and kernel requirement:

```yaml
version: '2'
services:
  first-service:
    build: ./first-service
    labels:
      io.balena.features.requires.sw.balena-os: '>6.3.0+rev4'
  second-service:
    image: my-second-image
    labels:
      io.balena.features.requires.sw.linux: '>5.15.*'
```

#### Optional containers

By default, when a container requirement is not met, none of the services are deployed to the device. However, in a multi-container release, it is possible to ignore those services that do not meet requirements with the other services being deployed as normal. To do so, we make use of the `io.balena.features.optional: 1` label to indicate which services should be considered optional.

In the `docker-compose.yml` file, add the `io.balena.features.optional: 1` to the labels list for each service you wish to mark as optional. In the following example, even if the `first-service` requirements fail, the `second-service` service will still be deployed.

```dockerfile
version: '2'
services:
  first-service:
    build: ./first-service
    labels:
      io.balena.features.requires.hw.device-type: 'jetson-nano'
      io.balena.features.optional: '1'
  second-service:
    build: ./second-service
```

{% hint style="warning" %}
When updating between releases, if the new version of and optional service has unmet requirements, the old version of the service will still be killed.
{% endhint %}


# Develop with Apps

{% hint style="warning" %}
Apps are an experimental feature. To enable them, go to *Preferences → Experimental Options* and make sure "Display Apps" is checked.
{% endhint %}

An App is a multi-container resource which can be deployed to multiple fleets. Apps are intended to offer standalone functionality and can be constructed entirely or partially from [blocks](/learn/develop/blocks). Apps are designed to facilitate functionality sharing between both public and private fleets. They can be published on [balenaHub](https://hub.balena.io/) in order to allow other users outside of your balenaCloud organization to install and utilize them on their own fleets. Apps can exist independently to solve for a complete use case.

## What can Apps be used for?

Apps are a way to group together multiple containers that are deployed to a fleet of devices together in order to perform a complete function. They differ from blocks since they are intended to work standalone and do not require any further development or external containers to function for their use case.

Apps exist today for those developers who wish to share what they have built on [balenaHub](https://hub.balena.io/) in order to enable deployment to other fleets owned by other people using balenaCloud. Apps are created within balenaCloud, releases are pushed in the exact same way as with fleets, and then they can be [marked public](#publishing-an-app-on-balenahub) to publish them on balenaHub and share with others. In this manner, one App can be installed on multiple fleets.

An example of an App constructed in this way is [balenaSense](https://github.com/balenalabs/balena-sense). BalenaSense is built from the [dashboard](https://github.com/balenablocks/dashboard) and [connector](https://github.com/balenablocks/connector) blocks along with some additional containers. An App such as balenaSense could be deployed to a fleet to create an air-quality monitoring network, for example.

## Creating Apps

If you’ve previously worked with fleets on balenaCloud, the process of creating an App and [deploying](/learn/deploy/deployment) a release is very similar.

In order to create your own App, the code needs to be in a public GitHub repository. When an App is deployed, the latest code is pulled from GitHub. This will change in the future as and when we add support for private apps. The App has to include a [balena.yml](https://docs.balena.io/learn/develop/pages/s7Pxw0dDwcjBAKYb253o#balena.yml-configuration-file) file in the root directory of the project. Here's a balena.yml file of [balenaDash](https://github.com/balenalabs/balena-dash) for reference:

```yaml
name: balenaDash
description: >-
  Raspberry Pi-powered digital signage or website viewer, remotely accessible
  from anywhere.
type: sw.application
assets:
  repository:
    type: blob.asset
    data:
      url: 'https://github.com/balenalabs/balena-dash'
  logo:
    type: blob.asset
    data:
      url: >-
        https://raw.githubusercontent.com/balenalabs/balena-dash/master/assets/logo.png
data:
  applicationConfigVariables:
    - BALENA_HOST_CONFIG_gpu_mem: 128
    - BALENA_HOST_CONFIG_dtoverlay: 'vc4-fkms-v3d'
  applicationEnvironmentVariables:
    - SHOW_CURSOR: 0
    - CONTROL_TV: 0
    - ENABLE_GPU: 0
    - KIOSK: 1
    - PERSISTENT: 1
    - PORTAL_SSID: balenaDash
    - PORTAL_PASSPHRASE: balenaDash
    - ACTIVITY_TIMEOUT: 600
    - LAUNCH_URL: ''
    - ROTATE_DISPLAY: normal
    - WINDOW_POSITION: '0,0'
    - LOCAL_HTTP_DELAY: 0
    - FBCP_DISPLAY: ''
  defaultDeviceType: raspberrypi4-64
  supportedDeviceTypes:
    - raspberrypi4-64
    - fincm3
    - raspberrypi3
    - raspberrypi3-64
    - intel-nuc
    - genericx86-64-ext
    - raspberrypi400-64
version: 2.0.0
```

Next, navigate to the Apps tab in the sidebar and click the `Create App` button in the balenaCloud dashboard. Fill the details for your App in the modal, and click `Create new app` button to create your App. Next, we need to push a new release to your newly created App on balenaCloud. If you are new to this, then follow the [Getting Started](/learn/getting-started) guide.

## Publishing an App on balenaHub

By default, Apps that you create within the balenaCloud dashboard are private and only accessible by the owner along with any other teams or members that you explicitly grant access to. When you are ready to release, head to the Settings tab in the sidebar and add your App’s GitHub repository to the Repository URL section. Next, toggle the App visibility button to on for your App to be visible on balenaHub. You’re free to toggle the visibility on and off as necessary at any time.

<figure><img src="/files/Ly3wEGEbJJKL1Xw3fLqv" alt=""><figcaption></figcaption></figure>

Apps marked with visibility set to ‘on’ in the dashboard will be made available as another resource for the community on balenaHub. Users can deploy Apps from balenaHub to their own fleets managed in their own balenaCloud accounts using the `Deploy` button with each App.

## Deploying Apps from balenaHub

<figure><img src="/files/bvLZlJvtKgvldaGHWFy9" alt=""><figcaption></figcaption></figure>

When the deploy button on balenaHub is used, the balenaCloud builder will fetch the latest source from the linked GitHub repository and create a new build for the chosen fleet. This process uses the [Deploy with balena](/learn/deploy/deploy-with-balena-button) workflow in order to guide users through the process of creating/signing in to a balenaCloud account, creating a fleet and deploying the App.

## Support access

If you require assistance with an App and have contacted balena for support, agents may ask you to ‘enable support access’ for the App. This can be achieved via toggling the `Support access` setting, found within the settings page to on.

Once enabled, for security reasons, the support access toggle will revert back to ‘off’ at the time specified.

<figure><img src="/files/XWGwFT1ZOTjGjldadeut" alt=""><figcaption></figcaption></figure>

## Release management

To deploy new releases of your App, you can use the `balena push` command using the balenaCLI. The Releases tab in the sidebar will show the list of all releases of your App.

An App can be pinned to a specific release which will control which release is used to display content on balenaHub. Note that when a user deploys an app, the latest code is pulled from Github and is independent of this setting.

## Transfer App ownership

Apps with all their associated releases and members can be transferred to any other balenaCloud organization. App transfers are between a source and a target organization.

Only organization administrators can initiate and complete App transfers. You must coordinate with one of the receiving organization's administrators to perform the following actions:

* Take note of the App name in the source organization and your balenaCloud username (in the top-right drop-down menu).
* Ask an administrator of the target balenaCloud organization to create a new empty App using the same block name (the type doesn't need to match).
* Ask the administrator of the target balenaCloud organization to add you as a member of the newly created App with a Developer role, using your username. If you are an administrator of the target organization, you already have access to the new App & this step can be skipped.
* In the source organization, select Settings --> Set App ownership and pick the target organization from the list to complete the transfer.

{% hint style="warning" %}
If the dropdown for the destination organization is empty and grayed out, ensure that you have created an empty App in the target organization with the same name as the source App, and that the user that is transferring ownership of the App from the source organization has been added as a Developer to the target App.
{% endhint %}

Once the ownership has been set to the new owner, the source App owner will no longer be a member of the target App. If required, you will need to invite them to become a member of the App again. All other members of the source App will retain their membership of the target App once the transfer is complete.

## The future roadmap

The functionality for Apps we have today is only the start. Apps added via the dashboard can be shared on balenaHub for others to deploy to their own fleets which serves to help others, and we’ll continue building out to expand to installing private Apps on private fleets, automatic updates, and eventually the ability to install multiple Apps on a single fleet. Keep an eye on [our blog](https://balena.io/blog) for all the latest news.


# Develop with blocks

A block is a container image that can be added to a multicontainer fleet in order to provide specific functionality. Blocks are intended to reduce the friction of app development by making it easier to re-use functionality, much like software packages.

Similar to how software developers don't want to keep rewriting common functions, IOT developers don't want to keep creating containers for common tasks, such as handling Bluetooth connections or interacting with attached displays. Blocks provide solutions to common IoT application requirements, which developers can re-use to enable their fleet.

For example, getting a browser to run well in a container is a tedious task. Hence, why not use the [browser block](https://github.com/balenablocks/browser) to get things up and running faster..

<figure><img src="/files/V5Ve8mf8Br4LIBug2Y01" alt=""><figcaption></figcaption></figure>

## Getting Started with blocks

Since blocks are container images, they can be added to a multicontainer fleet. To use a block in your fleet, add the block's image as a new service in the `services` section of your app's `docker-compose.yml` file. This is similar to how we would build [multicontainer fleets](https://docs.balena.io/learn/develop/pages/CORva05iOMsT8cTRP8aC#docker-compose.yml-file).

Here's an example of using the [browser block](https://github.com/balenablocks/browser) in a sample multicontainer fleet already running 2 services.

```yaml
version: '2'

services:
  # Browser block service added to the multicontainer fleet
  browser:
    image: bh.cr/balenablocks/browser-aarch64
    privileged: true
    network_mode: host

  # Existing services in the multicontainer fleet
  balena-node-hello-world:
    build: ./balena-node-hello-world
    restart: always
    depends_on:
      - browser
    ports:
      - '80'
  importantBananaDb:
    image: importantBanana/db:latest
    ports:
      - '8080'
    environment:
      DB_ROOT_PASSWORD: 'potassium'
      RUN_MODE: 'super-secure'
```

Each block will have their own set of [docker-compose fields](/reference/supervisor/docker-compose) which are required to configure the container they run within. Do take care of syntax and conflicts in the docker-compose.yml file when composing and deploying your multicontainer configuration.

More resources:

1. Blog on [Introduction to blocks](https://www.balena.io/blog/introducing-balenablocks-jumpstart-your-iot-app-development/).
2. Check out our guide on [how to compose multicontainer fleets](https://www.balena.io/blog/two-projects-one-device-turn-your-raspberry-pi-into-a-multitool/) for more details.
3. Video tutorial on [IoT Happy Hour](https://youtu.be/Mllay6Z2-qQ?t=1440) about using balenaBlocks and building an [environmental sensor app](https://github.com/balenalabs-incubator/ruuvitag) using sensor, connector, and dashboard block.

## Creating your own block

Since blocks are container images, the process to create them is very similar to creating any other container. To learn more about what makes a good candidate for a block, refer to this [blog post](https://www.balena.io/blog/how-to-make-your-own-balenablocks-simple-drop-in-edge-app-functionality/).

In order to create your own block, the code needs to be in a GitHub repository. It has to [include a balena.yml file](https://docs.balena.io/learn/develop/pages/s7Pxw0dDwcjBAKYb253o#balena.yml-configuration-file) in the root directory of the project. Here's a balena.yml file of the [browser block](https://github.com/balenablocks/browser/) for reference:

```yml
name: browser
description: >-
  a hardware accelerated web browser to present internal and external URLs on a
  connected display
version: 2.3.2
type: sw.block
assets:
  repository:
    type: blob.asset
    data:
      url: 'https://github.com/balenablocks/browser'
  logo:
    type: blob.asset
    data:
      url: 'https://raw.githubusercontent.com/balenablocks/browser/master/logo.png'
data:
  defaultDeviceType: raspberrypi3
  supportedDeviceTypes:
    - raspberrypi4-64
    - fincm3
    - raspberrypi3
    - raspberrypi3-64
    - raspberrypi400-64
    - intel-nuc
    - genericx86-64-ext
```

Next, navigate to the `Blocks` tab in the sidebar and click the `Create block` button in the balenaCloud dashboard.

<figure><img src="/files/3HUgBVkDg5BzRQH4eQSM" alt=""><figcaption></figcaption></figure>

Fill the details for your block in the modal, and click `Create new block` button to create your block.

<figure><img src="/files/tdNtc7HgqKG517unQ3NO" alt=""><figcaption></figcaption></figure>

Next, we have to [push a new release](/learn/deploy/deployment#balena-push) from your project to your newly created block on balenaCloud. If you are new to this, then follow the [Getting Started](/learn/getting-started) guide. After the release has been created, your block is ready. You can manage, modify and iterate further on your block from the balenaCloud dashboard.

## Release management for blocks

To deploy new releases of your block, you can use the [balena-push](/learn/deploy/deployment#balena-push) command using the [balenaCLI](https://github.com/balena-io/balena-cli). The `Releases` tab in the sidebar will show the list of all releases of your block.

<figure><img src="/files/BEvIsbRRoYeZObpwkG7l" alt=""><figcaption></figcaption></figure>

By default, the block is set to `track latest`, which means that new releases are immediately tagged as the default release for the block. Expanding this *Default release* dropdown menu displays all successful releases for the block, and you can select a specific release to pin the block to. When a particular release is selected, that release will be tagged as the default release of your block. After pinning to a specific release, releases will not be deployed until the *Default release* is updated to a newer release or it's set back to `track latest`.

<figure><img src="/files/PTxDEJizNA0EV4Z4Ps14" alt=""><figcaption></figcaption></figure>

## Making your block public

When a block is created on balenaCloud, it won't automatically be visible on balenaHub. When the block's visibility is toggled to `public`, it will get listed in the [Blocks section](https://hub.balena.io/blocks) of balenaHub. Blocks aren't joinable like fleets or forkable like projects. Instead, the balenaHub page would provide the container image reference for the block, and instructions on how to deploy and use the block in your own fleet.

When blocks are private, you can iterate, test and build more functionality before making it available to the world. When you are ready to release, head to the `Settings` tab in the sidebar and add your block's GitHub repository to the `Repository URL` section. Next, toggle the `Block visibility` button to `on` for your block to be visible on balenaHub. You’re free to toggle the visibility on and off as necessary at any time.

<figure><img src="/files/j3BNjiIg5kYdAOLaoCmO" alt=""><figcaption></figcaption></figure>

This would lead to your block being available on [balenaHub](https://hub.balena.io/blocks) for folks to use and build upon as soon as your submission has been marked as public. BalenaHub is the ever-growing library of blocks, projects and fleets contributed by the community.

## Using your block in other projects

The URL to pull your block image (the *image reference*) is available in balenaHub by clicking the `Use` button.

<figure><img src="/files/L1tBMwWxVHUniwCAnpSY" alt=""><figcaption></figcaption></figure>

This image reference can be used in a Dockerfile or docker-compose file to pull the *default release* image of your block.

Here's how to pull a specific release version given several available releases in the dashboard.

```yaml
services:
  # Browser block service added to the multicontainer fleet
  browser:
    image: bh.cr/balenablocks/browser-aarch64/2.3.8
    privileged: true
    network_mode: host
```

{% hint style="info" icon="message-exclamation" %}
Note the forward slash `/` instead of the colon `:` syntax when specifying the version in the URL. [Learn more](https://github.com/balena-io/open-balena-registry-proxy#usage).
{% endhint %}

Specifying a revision via `+rev_` is not supported in image URLs as the plus sign is considered a special character. Instead, we will default to pulling the latest revision when a release version is provided.

So if there are multiple revisions of a release, for example `2.3.8`, `2.3.8+rev1`, and `2.3.8+rev2`, specifying `2.3.8` in the image reference will result in `2.3.8+rev2` being pulled.

During development you may want to pull a draft release for testing. Since draft releases are not included in the latest release track, you must specify the whole version string including the build stamp.

```yaml
services:
  # Browser block service added to the multicontainer fleet
  browser:
    image: bh.cr/balenablocks/browser-aarch64/2.4.1-1648554962021
    privileged: true
    network_mode: host
```

You can also refer to a release by its build commit by copying the commit hash from the first column of the releases dashboard.

```yaml
services:
  # Browser block service added to the multi-container fleet
  browser:
    image: bh.cr/balenablocks/browser-aarch64/11e1ee23d7ddf6ab6da99bac26c9d274
    privileged: true
    network_mode: host
```

Having the image reference available on balenaHub block page makes it easy to develop with blocks.


# Extra firmware

Some devices require specific Linux firmware files to enable hardware functionality such as WiFi, Bluetooth, or GPU acceleration. The balenaOS root filesystem has limited space, which restricts the firmware that can be included by default. The extra firmware block allows you to incorporate device-specific firmware into your fleet without waiting for an OS release.

### How it works

The extra firmware block mirrors the [linux-firmware](https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/) repository and copies the required firmware files into a named volume `extra-firmware`, which mounts at `/extra-firmware` in container. When the feature is enabled, balenaOS configures itself to look in this volume location for Linux firmware in addition to the default firmware paths.

### Requirements

To use the extra firmware feature, your device must meet the following requirements:

| Requirement | Version           |
| ----------- | ----------------- |
| BalenaOS    | v6.10.7 or higher |
| Supervisor  | v17.5.2 or higher |

### Using the extra firmware block

#### Step 1: Add the firmware block to your fleet

Add the extra firmware block as a service in your `docker-compose.yml` file. We release firmware blocks for the following architectures:

| Architecture | Image                                    |
| ------------ | ---------------------------------------- |
| armv6        | `bh.cr/balena_os/linux-firmware-armv6hf` |
| armv7        | `bh.cr/balena_os/linux-firmware-armv7hf` |
| armv8        | `bh.cr/balena_os/linux-firmware-aarch64` |
| x86          | `bh.cr/balena_os/linux-firmware-amd64`   |

The firmware block **must** include the `io.balena.features.extra-firmware` label to enable the feature:

```yaml
version: '2.4'

services:
  firmware:
    image: bh.cr/balena_os/linux-firmware-aarch64
    labels:
      io.balena.features.extra-firmware: '1'
```

#### Step 2: Enable the feature in other services (optional)

If you have other services that need to add firmware files to the extra firmware location, you can also apply the `io.balena.features.extra-firmware` label to those services:

```yaml
version: '2.4'

services:
  firmware:
    image: bh.cr/balena_os/linux-firmware-aarch64
    labels:
      io.balena.features.extra-firmware: '1'

  my-service:
    build: ./my-service
    labels:
      io.balena.features.extra-firmware: '1'
```

#### Step 3: Deploy and reboot

After deploying a release that includes the firmware block, you must either reload the drivers that use the extra firmware, or reboot the device for the firmware to take effect. This is especially important for firmware that is used early in the application startup process.

You can initiate a reboot using the [Supervisor API](/reference/supervisor/supervisor-api#post-v1-reboot):

```bash
curl -X POST \
    -H "Content-Type:application/json" \
    -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY"
    "$BALENA_SUPERVISOR_ADDRESS/v1/reboot"
```

{% hint style="warning" %}
To use the Supervisor API, your service must have the `io.balena.features.supervisor-api` [label](/reference/supervisor/docker-compose#labels) set.
{% endhint %}

### Example configuration

Here is a complete example of a multicontainer fleet using the extra firmware block alongside an application service:

```yaml
version: '2.4'

services:
  firmware:
    image: bh.cr/balena_os/linux-firmware-aarch64
    labels:
      io.balena.features.extra-firmware: '1'

  custom-firmware:
    build: ./custom-firmware
    depends_on:
      - firmware
    labels:
      io.balena.features.extra-firmware: '1'
      io.balena.features.supervisor-api: '1'
    command:
      - /bin/sh
      - -c
      - |
        cp /usr/share/my-firmware/* /extra-firmware/
        exec /usr/src/app/wait-then-restart.sh
    restart: always
```


# Communicate outside the container

In many situations, the code running in your container will need some way to communicate with outside services and devices, whether this means the host OS, the device supervisor, the network, or internal and external storage. Below, you'll find different methods for external communication, as well as some tips and tricks to keep in mind.

## Host OS

### Environment variables

Inside your running container, you'll have access to a number of `BALENA_` namespaced environment variables, which provide information from the system outside the container:

On all balenaOS versions of the OS, both `RESIN_` and `BALENA_` variables will be injected into the container to maintain backwards compatibility.

|           Variable           |                                                                                                                                                                                                                    Description                                                                                                                                                                                                                   |
| :--------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|     `BALENA_DEVICE_UUID`     |                                                                                                                                                                              The unique identification number for the device. This is used to identify it on balena                                                                                                                                                                              |
|        `BALENA_APP_ID`       |                                                                                                                                                                                              ID number of the balena fleet the device is associated.                                                                                                                                                                                             |
|       `BALENA_APP_NAME`      |                                                                                                                                                                                            The name of the balena fleet the device is associated with.                                                                                                                                                                                           |
| `BALENA_DEVICE_NAME_AT_INIT` |                                                                                                                                                                                                  The name of the device on first initialization.                                                                                                                                                                                                 |
|     `BALENA_DEVICE_TYPE`     |                                                                                                                                                                                                    The type of device the fleet is running on.                                                                                                                                                                                                   |
|           `BALENA`           |                                                                                                                                                                       The `BALENA=1` variable can be used by your software to detect that it is running on a balena device.                                                                                                                                                                      |
|  `BALENA_SUPERVISOR_API_KEY` |                                                   Authentication key for the supervisor API. This makes sure requests to the supervisor are only coming from containers on the device. See the [Supervisor API reference](#supervisor) for detailed usage. For multicontainer the service needs the [io.balena.features.supervisor-api](/reference/supervisor/docker-compose#labels) label set.                                                  |
|  `BALENA_SUPERVISOR_ADDRESS` |                                                                                                                The network address of the supervisor API. Default: `http://127.0.0.1:48484`. For multicontainer the service needs the [io.balena.features.supervisor-api](/reference/supervisor/docker-compose#labels) label set.                                                                                                                |
|   `BALENA_SUPERVISOR_HOST`   |                                                                                                                             The IP address of the supervisor API. Default: `127.0.0.1`. For multicontainer the service needs the [io.resin.features.supervisor-api](/reference/supervisor/docker-compose#labels) set                                                                                                                             |
|   `BALENA_SUPERVISOR_PORT`   |                                                                                                                      The network port number for the supervisor API. Default: `48484`. For multicontainer the service needs the [io.balena.features.supervisor-api](/reference/supervisor/docker-compose#labels) label set.                                                                                                                      |
|       `BALENA_API_KEY`       | API key which can be used to authenticate requests to the balena backend. Can be used with the SDKs on the device. **WARNING** This API key gives the code permissions to affect the device's metadata in the balena API; refer to our [security documentation](/learn/introduction/security) for more details. For multicontainer the service needs the [io.balena.features.balena-api](/reference/supervisor/docker-compose#labels) label set. |
|   `BALENA_HOST_OS_VERSION`   |                                                                                                                                                                                                            The version of the host OS.                                                                                                                                                                                                           |
|    `BALENA_DEVICE_RESTART`   |                                                                                                                                                         This is an internal mechanism for restarting containers and can be ignored as it's not very useful to app code. Example: `1.13.0`                                                                                                                                                        |

Here's an example from a Raspberry Pi 3:

```bash
root@raspberrypi3-cc723d7:/# printenv | grep BALENA
BALENA_SUPERVISOR_API_KEY=1111deadbeef2222
BALENA_APP_ID=157270
BALENA_DEVICE_TYPE=raspberrypi3
BALENA=1
BALENA_SUPERVISOR_ADDRESS=http://127.0.0.1:48484
BALENA_SUPERVISOR_HOST=127.0.0.1
BALENA_DEVICE_UUID=cb6f09d18ab4c08556f54a5bd7cfd353d4907c4a61998ba8a54cd9f2abc5ee
BALENA_API_KEY=deadbeef12345
BALENA_APP_NAME=Example
BALENA_DEVICE_NAME_AT_INIT=damp-haze
BALENA_HOST_OS_VERSION=balenaOS 2.20.0
BALENA_SUPERVISOR_PORT=48484
```

### D-Bus communication with host OS

In some cases it's necessary to communicate with the host OS systemd to perform actions on the host. To do this you can use [dbus](https://www.freedesktop.org/wiki/Software/dbus/). In order to ensure that you are communicating to the host OS systemd and not the systemd in your container it is important to set `DBUS_SYSTEM_BUS_ADDRESS` for all D-Bus communication. The setting of that environment variable is different for older and newer devices (based on the balena supervisor version), choose the line that is correct for your device's OS version (can be found in your device dashboard):

{% hint style="danger" %}
**Giving dbus access to the host significantly lowers the security of your container. Treat the container as if it was running `privileged` and had full root access to the host.**

It's recommended to only give that level of access to containers that have a single and well-defined purpose, very limited interfaces and a tighly-controlled lifecycle.
{% endhint %}

```
# for balena supervisor versions 1.7.0 and newer (both balenaOS 1.x and 2.x) use this version:
DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket
```

```
# for balena supervisor before 1.7.0 use this version:
DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host_run/dbus/system_bus_socket
```

Below you can find a couple of examples. All of them requires either prepending the command with the above `DBUS_SYSTEM_BUS_ADDRESS=...` or setting the variable for all commands by running `export DBUS_SYSTEM_BUS_ADDRESS=...` with the correct environment variable value from above.

In multicontainer fleets, you can also set `DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket` in the `environment` section of your service in the `docker-compose.yml` file:

```yaml
version: '2'
services:
  someservice:
    environment:
      - 'DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket'
    labels:
      io.balena.features.dbus: '1'
```

{% hint style="warning" %}
Please be aware that setting `DBUS_SYSTEM_BUS_ADDRESS` as a service or environment variable and enabling systemd at the same time might introduce unexpected side effects. Systemd might start to interact with the host system instead of the container. These interactions can potentially cause balenaOS devices to disconnect from balenaCloud or even fall offline. Hence, users are advised to prefer prepending the command with the variable definition.
{% endhint %}

{% hint style="warning" %}
To use the `dbus-send` command in the example you will need to install the `dbus` package in your Dockerfile if you are using the Debian image, or check under what name does your chosen operating system supply the `dbus-send` executable.
{% endhint %}

#### Change the Device hostname

Changing the device hostname via a dbus-send method invocation of `org.freedesktop.hostname1.SetHostname` is no longer possible, due to the fact that this would attempt to write to `/etc/hostname`, which on the [host OS](/reference/os/overview) is stored in the read-only root partition. To change the device hostname, use the [balena supervisor API](/reference/supervisor/supervisor-api#patch-v1-device-host-config)

#### Rebooting the Device

```bash
DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
  dbus-send \
  --system \
  --print-reply \
  --dest=org.freedesktop.systemd1 \
  /org/freedesktop/systemd1 \
  org.freedesktop.systemd1.Manager.Reboot
```

#### Stopping a systemd service

At times, you may wish to stop a running service on the host OS, such as `bluetooth.service`, in order to run your own instance of bluez containerized.

```bash
DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
  dbus-send \
  --system \
  --print-reply \
  --dest=org.freedesktop.systemd1 \
  /org/freedesktop/systemd1 \
  org.freedesktop.systemd1.Manager.StopUnit \
  string:bluetooth.service string:replace
```

#### Checking if device time is NTP synchronized

```bash
DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
  dbus-send \
  --system \
  --print-reply \
  --reply-timeout=2000 \
  --type=method_call \
  --dest=org.freedesktop.timedate1 \
  /org/freedesktop/timedate1  \
  org.freedesktop.DBus.Properties.GetAll \
  string:"org.freedesktop.timedate1"
```

The reply would look like this:

```variant
method return time=1474008856.507103 sender=:1.12 -> destination=:1.11 serial=4 reply_serial=2
   array [
      dict entry(
         string "Timezone"
         variant             string "UTC"
      )
      dict entry(
         string "LocalRTC"
         variant             boolean false
      )
      dict entry(
         string "CanNTP"
         variant             boolean true
      )
      dict entry(
         string "NTP"
         variant             boolean true
      )
      dict entry(
         string "NTPSynchronized"
         variant             boolean true
      )
      dict entry(
         string "TimeUSec"
         variant             uint64 1474008856505839
      )
      dict entry(
         string "RTCTimeUSec"
         variant             uint64 1474008857000000
      )
   ]
```

The entry `NTPSynchronized` shows `true`, so the device is NTP synchronized. (The key `NTP` only shows whether the device is using the systemd service `systemd-timesyncd`; starting from balenaOS 2.13.1, the `chrony` service is used for time management.)

{% hint style="warning" %}
For additional D-Bus examples see the [balenaOS masterclass](https://docs.balena.io/learn/develop/pages/w5ScyUMPmnTE66tLwooR#id-13.-advanced-dbus-examples)
{% endhint %}

### Blacklisting kernel modules won't work

Since the `/etc/modules` you see in your container belongs to the container's filesystem and is not the same as `/etc/modules` in the host OS, adding kernel modules to the modules blacklist in the container will have no effect. So in order to remove a module, you need to explicitly do a [`rmmod`](http://linux.die.net/man/8/rmmod).

## Supervisor

{% hint style="warning" %}
In multicontainer fleets, the `io.balena.features.supervisor-api` label must be applied for each service that requires access to the Supervisor API. If you have devices with a supervisor version lower than 7.22.0, you should use `io.resin.features` labeling as that will ensure backward compatibility
{% endhint %}

### Reboot from Inside the Container

You may notice that if you issue a `reboot`, `halt`, or `shutdown` your container either gets into a weird zombie state or doesn't do anything. The reason for this is that these commands do not propagate down to the host OS system. If you need to issue a `reboot` from your container you should use the supervisor API as shown:

```
curl -X POST --header "Content-Type:application/json" \
    "$BALENA_SUPERVISOR_ADDRESS/v1/reboot?apikey=$BALENA_SUPERVISOR_API_KEY"
```

[Read more about the supervisor API](/reference/supervisor/supervisor-api#post-v1-reboot)

{% hint style="warning" %}
`BALENA_SUPERVISOR_API_KEY` and `BALENA_SUPERVISOR_ADDRESS` should already be in your environment by default for single containers, but for multicontainer devices the service needs the [io.resin.features.supervisor-api](/reference/supervisor/docker-compose#labels) set . You will also **need** `curl` installed in your container.
{% endhint %}

Alternatively, it is possible to reboot the device via the D-Bus interface as described above.

### Writing to logs on the Dashboard

Anything written to `stdout` and `stderr` should appear on the device's dashboard logs. Have a look at some of our [example projects](https://github.com/balenalabs) on GitHub to get an idea of how to do this.

## Network

BalenaEngine supports [host](https://docs.docker.com/network/host/) and [bridge](https://docs.docker.com/network/bridge/) network modes:

* Host mode allows a service to use all host network interfaces.
* Bridge mode uses a user-defined bridge network interface, to which service containers are connected.

Any service that uses host networking does not have to define ports for traffic ingress, and a service can bind to all interfaces of the host. Single container releases always use host networking.

In contrast to host networking, bridge networks isolate all services from the host, requiring services to explicitly define open ports to allow traffic from the host to be passed to them (all outgoing traffic is permitted). By default, multicontainer releases use a bridge network.

### Single container

Single container releases always use host networking, allowing them to bind to any of the host's network interfaces. If security and sandboxing are required for either privilege level or to ensure self-contained networking, then a multicontainer release should be created, even if only a single service is required.

### Multicontainer

Multicontainer releases use a user-defined bridge network by default. No ports are exposed to the host and must be explicitly enabled through the `ports` [keyword](https://docs.docker.com/compose/compose-file/compose-file-v2/#ports). Services on the same bridge network have access to all other services' ports.

The following [sample multicontainer](/learn/develop/multicontainer#named-volumes) `docker-compose.yml` file allows incoming traffic on port 80 to the `proxy` service, but the `frontend` and `data` services are isolated from the host and only accessible via the bridge network, which all services are connected to.

```yaml
version: '2'
services:
  frontend:
    build: ./frontend
    expose:
      - '80'
  proxy:
    build: ./haproxy
    depends_on:
      - frontend
      - data
    ports:
      - '80:80'
  data:
    build: ./data
    expose:
      - '8080'
```

{% hint style="warning" %}
Exposing ports via the expose keyword is optional and a way of documenting which ports are used, but does not map or open any ports. By default, services on the same bridge network have access to all other services' ports.
{% endhint %}

For multicontainer releases, setting the service `network_mode` to `host` in `docker-compose.yml` allows the container to share the same network namespace as the host OS.

Balena `docker-compose.yml` files support the creation of multiple bridge networks allowing you to compartmentalize further, so that some services exist in only one defined network, whereas others may be able to communicate in many. The `aliases` [keyword](https://docs.docker.com/compose/compose-file/compose-file-v2/#aliases) for providing alias names for services (including FQDNs) and [IPAM bridge networks](https://docs.docker.com/compose/compose-file/compose-file-v2/#network-configuration-reference) are also supported.

{% hint style="warning" %}
For more information on networking with balena, see the [balena services masterclass](https://docs.balena.io/learn/develop/pages/AVNPbJlAuDxvDl7GfgI5#id-4.-networking-types).
{% endhint %}

### Public device URLS

Balena currently exposes port 80 for web forwarding. To enable web forwarding on a specific device, navigate to the device's **actions** tab on the balenaCloud dashboard and select the `Enable a public URL for this device` button. For more information about device URLs see the [Device Management Page](/learn/manage/actions#public-device-url)

<figure><img src="/files/VBOF5rofLo5j5rrkqKMw" alt=""><figcaption></figcaption></figure>

Running a server listening on port 80 with public device URL enabled will allow you to serve content from the device to the world. Here is an example of an [express.js](https://expressjs.com/) server which will serve to the devices URL.

```javascript
var express = require('express');
var app = express();

app.get('/', function (req, res) {
	res.send('Hello World!');
});

var server = app.listen(80, function () {
	var host = server.address().address;
	var port = server.address().port;

	console.log('Example app listening at http://%s:%s', host, port);
});
```

### Using DNS resolvers in your container

In the balena host OS [dnsmasq](https://www.thekelleys.org.uk/dnsmasq/doc.html) is used to manage DNS since balenaOS 1.1.2. This means that if you have dnsmasq or other DNS resolvers such as [bind9](https://bind9.net/) running in your container, it can potentially cause problems because they usually try to bind to `0.0.0.0`, which interferes with the host dnsmasq. To get around this, you need to add `bind-interfaces` to your dnsmasq configuration in your container or make sure your server only binds to external IPs, and there shouldn't be conflicts anymore.

## Storage

### Persistent Storage

If you have data or configurations that you would like to persist through application and host OS updates, you have the option to keep them in persistent storage. Persistent storage is a good place to write system logs and other application data that should remain untouched even as your code changes.

**Before balenaOS v2.12.0**

On devices running OS versions before 2.12.0, the `/data` folder in the container is automatically linked to a directory on the host OS and guaranteed to persist across updates. The contents of the `/data` folder can be accessed via the host OS at `/mnt/data/resin-data/<APP ID>`.

The `/data` folder is not synced between devices in your fleet. In addition, the folder is unique to a specific fleet, so if you transfer your device to a new fleet the `/data` folder from the previous fleet will not be accessible in the container. It will, however, still be available via the host OS and if the device is moved back to the original fleet.

Note that the `/data` folder is **not** mounted when your project is building on our build servers, so you can't access it from your `Dockerfile`. The `/data` volume only exists when the container is running on the deployed devices.

**balenaOS v2.12.0 and above**

Beginning with balenaOS v2.12.0, persistent storage is handled through [named volumes](/learn/develop/multicontainer#named-volumes). The behavior is much the same as persistent storage on older host OS versions. In fact, for single-container fleets, the default `docker-compose.yml` sets up a `resin-data` named volume that links to a `/data` directory in the container. The only difference between this and earlier versions is that accessing this data via the host OS is done at `/var/lib/docker/volumes/<APP ID>_resin-data/_data`, rather than the `/mnt/data/resin-data/<APP ID>` location used with earlier host OS versions.

Named volumes can be given arbitrary names and can be linked to a directory in one or more containers. As long as every release includes a `docker-compose.yml` and the volume name does not change, the data in the volume will persist between updates.

When using named volumes, note that:

* If a device is moved to a new fleet, the old `/data` folder will be automatically purged.
* During the build process, data added to a container directory that is configured to link to a named volume will be copied to the volume the first time it's created on the device.

**Using a Supervisor with a version >= v10.0.0**

Since balena-supervisor v10.0.0, volumes are no longer automatically removed from disk when references to them are removed from a fleet's `docker-compose` file. This means that it's no longer possible for data to be lost due to the accidental rename of a volume.

If you change volume names regularly, your device will now continue to retain all previous volumes including their contents. To avoid this the supervisor API now provides an [endpoint to cleanup unreferenced volumes](/reference/supervisor/supervisor-api#cleanup-volumes-with-no-references). Additionally, it is possible to perform this action from the dashboard via the `Purge Data` action, found on the `Actions` tab for a device.

{% hint style="warning" %}
Volumes will continue to be removed automatically when moving a device between fleets.
{% endhint %}

**Transfer large files**

If you have large files you would like your containers to have access to, you can transfer them from your computer directly to your device's SD card. First insert the SD card in your computer and find the `resin-data` partition. Then look for the folder associated with your application, which will either be at `/resin-data/<APP ID>` or `/docker/volumes/<APP ID>_<VOLUME NAME>/_<CONTAINER DIRECTORY>`, depending on your host OS version. Note that these directories will only exist after your application has been started at least once.

### Temporary directories

Note that the `/tmp` and `/var/tmp` directories in a container are not true [tmpfs](https://www.kernel.org/doc/html/latest/filesystems/tmpfs.html) volumes by default, and they are treated like any other ephemeral container layers.

As a result, you can expect that data in these directories will persist over a device reboot, but will **not** persist when a [services restart](/learn/manage/actions#restart-services) is triggered.

If you would like these directories to act more like `tmpfs` volumes and write to volatile memory, you can use [tmpfs mounts](https://docs.docker.com/storage/tmpfs/).

```yml
services:
  myapp:
    image: foo/bar
    tmpfs:
      - /tmp
      - /var/tmp
```

### Mounting external storage media

Since the release of multicontainer on the balena platform we no longer recommend the use of an initsystem in the container. This affects the way we deal with external storage since previously we relied on `systemd`/`OpenRC` and `/etc/fstab`.

The recommended way for mounting external storage media (SD cards, USB sticks, external drives, etc) into a container is now through the use of `mount`. Here we include a set of recommendations that will help you get started.

**balenaOS kernel support**

Before you start it's a good idea to check if the balenaOS kernel you are running was compiled with support for the filesystem you want to use. To do so, you can run this command on the **host** which will produce a list of supported filesystems: `cat /proc/filesystems`.

If your filesystem is not supported you can contact us through our [forums](https://forums.balena.io/) and we will be glad to help.

**Preparing the container**

In order to be able to detect external media dynamically you will need to run the container in privileged mode and enable `udevd` on it. This can be easily done if you are using [balena base images](/reference/base-images/balena-base-images) by:

* Adding `privileged: true` to your container's service definition on the `docker-compose.yml` file.
* Adding `ENV UDEV=on` to your container's `Dockerfile`.
* Running the entrypoint as the `root` user in the container namespace. This is often the default but can be set in your container's `Dockerfile` with `USER root` in the target build stage, or in your `docker-compose.yml` file with `user: root`.

This will ensure that the host propagates udev events into the container, enabling us to manipulate the device from within it.

**General tips for external media**

Devices can be selected in many ways, for example by its device name (`/dev` entry), label, or UUID. From a practical point of view, we recommend using labels (`LABEL=...` entries). Labels can easily be made the same across multiple cards or thumb drives, while you can still identify each device by their UUID. Also, `/dev` entries are not static on some platforms, and their value depends on which order the system brings up the devices. Device names or UUIDs are a good choice when you can easily identify or predict their values, for example within the context of a udev rule.

{% hint style="warning" %}
You can get a list of device names, labels and filesystem types by running `lsblk -f` (both on the host or container).
{% endhint %}

**Mounting**

To mount an external drive you can use Linux's `mount` command. Again, any selection method is supported:

```bash
mount -t <fstype> -o rw <device-name> <mount-point>
mount -t <fstype> -o rw -L <device-label> <mount-point>
mount -t <fstype> -o rw -U <device-uuid> <mount-point>
```

{% hint style="warning" %}
The mount point folder needs to exist for the mount to be successful.
{% endhint %}

For more information about the `mount` command see the [mount man page](https://man7.org/linux/man-pages/man8/mount.8.html).

**Unmounting**

To unmount an external drive you can use Linux's `umount` command:

```bash
umount <mount-point>
```

For more information about the `umount` command see the [umount man page](https://man7.org/linux/man-pages/man8/umount.8.html).

**Automounting/unmounting with udev rules**

The previous sections show how to manually mount or unmount external media. You probably want to automate this and have your media automatically mount/unmount when you plug it or unplug it. Fortunately this can be easily achieved by using udev rules.

First we create a rules file `usb.rules`:

```
ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="partition", RUN+="/bin/sh -c '/usr/src/scripts/mount.sh'"
ACTION=="remove", SUBSYSTEM=="block", ENV{DEVTYPE}=="partition", RUN+="/bin/sh -c '/usr/src/scripts/unmount.sh'"
```

These rules will trigger every time we plug or unplug a block partition device and run the scripts we provide (`/usr/src/mount.sh` or `/usr/src/unmount.sh`).

Copy both the rules and scripts to your container:

```dockerfile
COPY usb.rules /etc/udev/rules.d/usb.rules
COPY scripts /usr/src/scripts
```

Finally we need to write the `mount.sh` and `unmount.sh` scripts. These scripts will use `mount` and `umount` commands in the same way we described on the **Mounting** and **Unmounting** sections above.

You can find a fully working example of automounting/unmounting devices with udev rules in this [project](https://github.com/balena-io-playground/balena-storage).

**Sharing mounted devices across containers**

Note that currently it's not possible to share a mounted device across multiple containers. This is a feature that we are currently working on. This documentation will be updated once we add support for this feature.


# Interact with hardware


# Introduction

For many projects, you may need to control or have access to some external hardware via interfaces like GPIO, I2C or SPI. For single-container fleets, you will automatically have access to `/dev` and these interfaces as the container is run in [**privileged** mode](https://docs.docker.com/engine/reference/commandline/run/#/full-container-capabilities-privileged). This means you should be able to use any hardware modules like you would in a vanilla Linux environment.

Multicontainer fleets do not run containers in privileged mode by default. If you want to make use of hardware, you will have to appropriately configure your `docker-compose.yml` file to either set some services to privileged, using `privileged: true`, or use the `cap_add` and `devices` settings to map in the correct hardware access to the container.

As an example, here the `gpio` service is set up to use i2c and serial uart sensors:

```
gpio:
	build: ./gpio
	devices:
	  - "/dev/i2c-1:/dev/i2c-1"
	  - "/dev/mem:/dev/mem"
	  - "/dev/ttyACM0:/dev/ttyACM0"
	cap_add:
	  - SYS_RAWIO
```

{% hint style="warning" %}
If you are not using one of the Docker base images recommended in our [base images wiki](/reference/base-images/balena-base-images), then it's most likely you will need to handle the updating of `/dev` via [udev](https://www.freedesktop.org/software/systemd/man/udev.html) yourself.
{% endhint %}

For more details on interacting with external hardware, check out these guides:

* [GPIO](/learn/develop/hardware/gpio)
* [i2C and SPI](/learn/develop/hardware/i2c-and-spi)
* [USB](/learn/develop/hardware/usb)
* [Jetson Orin devices](/learn/develop/hardware/jetson-orin)


# GPIO

Recommended ways of interacting with GPIO on balena devices

## Raspberry Pi

All Raspberry Pi SBCs have a header that includes a number of [General Purpose Input/Output ("GPIO")](https://en.wikipedia.org/wiki/General-purpose_input/output) pins. These pins can be used to control external hardware such as LEDs, solenoids, motors, or other devices, as well as read data from various sensors. (The GPIO pins employ standard 3.3 volt logic and can't drive high current devices directly.) The earliest models used a 26 pin header, but all recent models use a 40 pin header.

#### Background

As Raspberry Pi models have evolved over the years, the hardware driving these GPIO pins has changed multiple times. The original Pi GPIO pins were directly driven from the SoC itself, while the Pi 5 uses a separate RP1 chip to drive the user-facing GPIO pins. For this reason, GPIO software libraries that use direct access to registers may stop working as hardware and kernel updates change the location of these registers.

This situation is very evident on libraries that depend on the long-deprecated `sysfs` interface, which is due to be removed completely from the Linux kernel.

The appropriate method to access GPIO features is via the standard Linux libgpiod library. Using a hardware abstraction such as this means the Linux kernel handles any differences in hardware that may be encountered between different models.

#### Library Access

The current Raspberry Pi GPIO libraries include:

* [Libgpiod](https://libgpiod.readthedocs.io/en/master/) is a C library and set of tools for interacting with the Linux GPIO character devices (/dev/gpiochipX).
* [Pinctrl](https://github.com/raspberrypi/utils/tree/master/pinctrl) is a more powerful replacement for raspi-gpio, a tool for displaying and modifying the GPIO and pin muxing state of a system. It accesses the hardware directly, bypassing the kernel drivers
* [Rpi-lgpio](https://rpi-lgpio.readthedocs.io/en/release-0.4/) is a compatibility package intended to provide compatibility with the rpi-gpio (aka RPi.GPIO) library, on top of kernels that only support the gpiochip device (and which have removed the deprecated sysfs GPIO interface).

These libraries have been tested to run equally well on multiple models of Raspberry Pi and various balenaOS and kernel versions. ([Example repository](https://github.com/balena-io-experimental/pi-gpio).)

Much of this information and the image above is an excerpt from "A history of GPIO usage on Raspberry Pi devices, and current best practices" by [Raspberry Pi Ltd](https://pip.raspberrypi.com/categories/685-whitepapers-app-notes/documents/RP-006553-WP/A-history-of-GPIO-usage-on-Raspberry-Pi-devices-and-current-best-practices.pdf).

## Beaglebone

Currently Beaglebone devices are running a new 4.1 kernel, unfortunately many of the userspace libraries haven't caught up yet so they only work with the older 3.8 kernel. Checkout the [Octalbonescript](https://github.com/theoctal/octalbonescript) JS library and a Node.js module here: <https://www.npmjs.com/package/octalbonescript_capemgr4_1>.

With this module you should be able to carry out basic GPIO and analog-to-digital conversion operations. To get you started we have a [example using this module](https://github.com/balena-io-playground/beaglebone-adc-node).

The [Adafruit BBIO](https://github.com/adafruit/adafruit-beaglebone-io-python) library enables GPIO, PWM, ADC, UART, SPI, and eQEP hardware access from Python.


# USB

## BalenaFin

On certain USB hubs, one can control the power per port. This is usually referred to as per port power switching or PPPS. BalenaFin 1.x uses the LAN9514 USB 2.0 hub + ethernet controller which supports PPPS. The recommended way to implement this is to make use of the [`uhubctl`](https://github.com/mvp/uhubctl) tool.

1. You can add `uhubctl` to your container

```dockerfile
ENV UDEV=on
RUN install_packages uhubctl
```

2. Once you have it installed, you can see the list of USB devices by simply running `uhubctl`

```bash
root@01d925a:/usr/src/app# uhubctl
Current status for hub 1-1 [0424:9514, USB 2.00, 5 ports]
  Port 1: 0503 power highspeed enable connect [0424:ec00]
  Port 2: 0100 power
  Port 3: 0100 power
  Port 4: 0103 power enable connect [0a12:0001]
  Port 5: 0503 power highspeed enable connect [0781:5567]
```

3. You can then turn off a particular port, in this case port 1 as follows -

```
root@01d925a:/usr/src/app# uhubctl -p 1 -a 0
Current status for hub 1-1 [0424:9514, USB 2.00, 5 ports]
  Port 1: 0503 power highspeed enable connect [0424:ec00]
Sent power off request
New status for hub 1-1 [0424:9514, USB 2.00, 5 ports]
  Port 1: 0000 off
```

4. If you run the `uhubctl` command again, you should see that port 1 is now off

```
root@01d925a:/usr/src/app# uhubctl
Current status for hub 1-1 [0424:9514, USB 2.00, 5 ports]
  Port 1: 0000 off
  Port 2: 0100 power
  Port 3: 0100 power
  Port 4: 0103 power enable connect [0a12:0001]
  Port 5: 0503 power highspeed enable connect [0781:5567]
```

## Raspberry Pi Family

`uhubctl` is also [supported](https://github.com/mvp/uhubctl#compatible-usb-hubs) on Raspberry Pi boards. Check the [balenaFin](#balenafin) section above for instructions on getting started with `uhubctl`


# I2C and Other Interfaces

### Raspberry Pi Family

Many sensors and peripherals use either the [I²C (Inter-Integrated Circuit)](https://en.wikipedia.org/wiki/I%C2%B2C) or the [SPI (Serial Peripheral Interface)](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus) to communicate with the CPU. In most linux environments, using this kind of low level communication requires enabling a kernel module. In balena containers this can be done in a similar way because the containers are run in `--privileged` mode.

#### I2C

I2C is enabled by default in BalenaOS via the `dtparam=i2c_arm=on` device tree parameter used on RaspberryPi devices. The i2c-dev module is loaded by the kernel automatically on startup. To access /dev/i2c-\* char device files from a multi-container application, you can either list each file in your docker-compose.yml using device mappings:

```dockerfile
services:
  my-service:
  ...
    devices:
      - "/dev/i2c-1:/dev/i2c-1"
```

or mark the container as privileged if you want to have all /dev/ nodes bind-mounted inside the container:

```dockerfile
services:
  my-service:
  ...
    privileged:true
```

Single-container fleets run in privileged mode by default. If security and sandboxing are required then a multicontainer release should be created, even if only a single service is required.

To get you started, here is an [example project](https://github.com/balena-labs-projects/balena-sense) that supports a variety of i2c sensors to build your own monitoring system for your environment and visualize data from a remote dashboard.

#### SPI

SPI is enabled by default on balenaOS via the `dtparam=spi=on` [device tree parameter](/reference/os/advanced#setting-device-tree-overlays-dtoverlay-and-parameters-dtparam). This default behavior can be modified by editing the [device configuration](/learn/manage/configuration#device-configuration-management).

For Node.js applications it should work out of the box with the [spi node module](https://www.npmjs.com/package/spi). For an example of this, check out this project: [digitiser](https://github.com/balena-io-playground/digitiser).

#### Serial

Serial is disabled by default on the Raspberry Pi 3. To enable it you will need to do the following:

* Edit the `config.txt` in `balena-boot` partition of the SD card and append the following lines.

```
enable_uart=1
```

#### 1-wire and Digital Temperature sensors

In order to work work with 1-wire and digital temperature sensors you will need to do the following:

* Edit the `config.txt` in `balena-boot` partition of the SD card and append the following lines.

```
dtoverlay=w1-gpio
```

* Add `modprobe w1-gpio && modprobe w1-therm` before your start scripts in either your package.json start command or Dockerfile `CMD` command.

An example of this is shown in our [Firebase Temperature Logger](https://github.com/balena-io-playground/firebaseDTL) project.

#### Using UART or Serial on Raspberry Pi 3

To enable UART on `GPIO14 / UART0 TX` and `GPIO15 / UART0 RX` , you will need to apply the `pi3-miniuart-bt` device tree overlay. This can be done in two ways:

1. Add the following Device (or Fleet) Configuration variable to your device (or Fleet).

```
BALENA_HOST_CONFIG_dtoverlay = pi3-miniuart-bt
```

2. The second, more manual way to enable this configuration is to mount the SD card on your development machine. Find the `resin-boot` partition and in there you should see the Raspberry Pi's boot files, one of which is called `config.txt`. Open this file up and add the following line to the end of the file:

```
dtoverlay=pi3-miniuart-bt
```

Now eject the SD card and pop it back into the RPI3, and you can boot the device up again.

To demonstrate this functionality, you can push this project (<https://github.com/balena-io-playground/rpi3-uart>) to your RPI3. You will also need to add a small jumper wire between `GPIO14 / UART0 TX` and `GPIO15 / UART0 RX`, so that the data sent out of the UART is read back in and displayed in the logs.

#### Raspberry Pi camera module

Depending on the version of your balenaOS, the system contains different version of the Raspberry Pi firmware, and you need to apply slightly different settings. In both cases you can either modify `config.txt` on the `resin-boot` partition of your SD card, or add the settings remotely by using `BALENA_HOST_CONFIG_variablename` settings in your [fleet or device configuration](/learn/manage/configuration).

**BalenaOS 1.16.0 and newer**

Set the following values in `config.txt`:

```
gpu_mem=128
start_x=1
```

or for remote update

* `BALENA_HOST_CONFIG_gpu_mem` to `128`
* `BALENA_HOST_CONFIG_start_x` to `1` in the fleet or device configuration.

**BalenaOS 1.8.0 and earlier**

Set the following values in `config.txt`:

```
gpu_mem=128
start_file=start_x.elf
fixup_file=fixup_x.dat
```

or for remote update

* `BALENA_HOST_CONFIG_gpu_mem` to `128`
* `BALENA_HOST_CONFIG_start_file` to `start_x.elf`
* `BALENA_HOST_CONFIG_fixup_file` to `fixup_x.dat` in the fleet or device configuration.

You will also need to add `modprobe bcm2835-v4l2` before your start scripts in either your `package.json` start command or Dockerfile `CMD` command.

An example of this is shown in our [Raspberry Pi python picamera](https://github.com/balenalabs/balena-rpi-python-picamera) project.

#### Raspberry Pi 7” Touchscreen Display

In order to work with the Raspberry Pi display you will need to do the following:

* Edit the `config.txt` in `resin-boot` partition of the SD card and append the following line.

```
device_tree_overlay=rpi-ft5406-overlay.dtb
```

If you want a quick example project to get you started with you new screen, you might want to checkout our [Raspberry Pi Electron starter App](https://github.com/balena-io-playground/electron-rpi-quick-start).

If you find that you need to change the orientation of you LCD screen, you can easily achieve this by adding the following key/value to your `/boot/config.txt` on your SD card:

```
lcd_rotate = 0
```

And set the value to either 0, 90, 180 or 270, depending on your desired orientation.

{% hint style="warning" %}
The 90 and 270 degrees rotation options require additional memory on GPU, so won't work with the 16M GPU split.
{% endhint %}

#### Customizing config.txt

These are some tips and tricks for customizing your raspberry pi. Most of them require changing settings in the `config.txt` file on the SD cards `boot` partition. See [here](/reference/os/advanced) for more details.

You can also set all of these variables remotely for a single device or the entire fleet using the Configuration tab on the device or fleet level respectively. If the setting in `config.txt` is `variable=value`, you can achieve the same settings by adding a configuration variable with `BALENA_HOST_CONFIG_variable` set to the value `value`. For example:

For simplicity, below all examples are using the `config.txt` formatting, but all of them are available to set remotely as outlined above.

For further details and explanation regarding the settings below you may check the official [`config.txt` documentation](https://www.raspberrypi.com/documentation/computers/config_txt.html).

**Binary Blobs for GPU/vcore**

This is necessary for any graphics acceleration or if you want to use the official raspberry pi camera module

```
gpu_mem=128
start_file=start_x.elf
fixup_file=fixup_x.dat
```

**Increase USB current throughput:**

This can be useful if you are running a power hungry USB peripheral like a 3G dongle.

```
max_usb_current=1
safe_mode_gpio=4
```

**overclock RPI2:**

```
arm_freq=1000
core_freq=500
sdram_freq=400
over_voltage=0
over_voltage_sdram_p=0
over_voltage_sdram_i=0
over_voltage_sdram_c=0
```

**OR**

```
arm_freq=1000
sdram_freq=500
core_freq=500
over_voltage=2
temp_limit=80 #Will throttle to default clock speed if hit.
```

**Fill the screen to the edges**

```
disable_overscan=1
overscan_left=4
overscan_right=4
overscan_top=4
overscan_bottom=4
```

### Beaglebone

Currently the Beaglebone devices are running a very new 4.1 kernel (which is obviously awesome), unfortunately many of the userspace libraries haven't caught up yet so they only work with the older 3.8 kernel. Luckily [ruth0000](https://github.com/ruth0000) was kind enough to patch the Octalbonescript JS library and made a lovely node.js module over here: <https://www.npmjs.com/package/octalbonescript_capemgr4_1>.

With this module you should be able to basic GPIO and analog-to-digital conversion stuff. To get you started we have a simple example using this module [here](https://github.com/balena-io-playground/beaglebone-adc-node).

{% hint style="warning" %}
The ADC voltage is only rated to 1.8V, if you apply more you risk frying the pin.
{% endhint %}

#### Capemgr support

{% hint style="danger" %}
Capemgr is only supported in balena BBB devices with a 4.1 linux kernel. This kernel was only enabled in production on `25-09-2015`. If you don't know which kernel you are running, open a web terminal to your BBB and run `uname -a`.
{% endhint %}

**Loading a Cape**

```bash
echo cape-universaln > /sys/devices/platform/bone_capemgr/slots
```

**Checking which Capes are loaded.**

```bash
cat /sys/devices/platform/bone_capemgr/slots
```

```bash
cat /sys/devices/platform/ocp/ocp:cape-universal/status

OCPDIR=/sys/devices/platform/ocp/ocp*
SLOTS=/sys/devices/platform/bone_capemgr/slots
```

#### Disable HDMI

Before provisioning, mount the `.img`, in the `flash-boot` partition you should see a file named `uEnv.txt_internal` open that up with your favorite text editor and add the following line to the bottom of the file:

```
fdtfile=am335x-boneblack-emmc-overlay.dtb
```

You should now be able to use any of the pins that used to be occupied by the HDMI. To test this you can run the following from your web terminal:

```bash
echo 74 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio74/direction
echo 1 > /sys/class/gpio/gpio74/value
```

Pin 41 of Header P8 should go high.

### IOT-GATE-iMX8

#### Serial ports

The IOT-GATE-iMX8 has at least one serial port that can be configured as either RS232 or RS485. To select the RS232 operating mode, in the host operating system, add the following line to `/mnt/boot/extra_uEnv.txt`:

```bash
uart_mode=rs232
```

Similarly, rs485 can be selected in the environment file as well. The device should be rebooted after setting the uart operating mode the for the changes to take effect.

### Up Squared

#### Serial Ports

Depending on the HAT Configuration defined in BIOS, the Up Squared UART communication on pins 8 and 10 can be performed using either `/dev/ttyS4` or `/dev/ttyS5`. Please consult the HAT Configurations menu in BIOS for details on how pins are configured on your device.

### Jetson Devices

#### Custom device trees

Loading of custom device trees in balenaOS for Nvidia boards is supported by the Jetson Nano, Jetson TX2 and Jetson Orin family of devices. The list of devices that support this function includes:

* Floyd Nano
* Jetson Nano SD-CARD
* Jetson Nano eMMC
* Jetson Nano 2GB Devkit SD
* JN30B Nano
* Photon Nano
* Astro TX2
* Jetson TX2
* Jetson TX2 NX (with Xavier NX Devkit)
* Orbitty TX2
* Photon TX2 NX
* Spacely TX2
* Jetson AGX Orin Devkit
* Jetson Orin NX in Xavier NX Devkit NVMe (16GB RAM)
* Jetson Orin Nano 8GB (SD) Devkit NVME

Loading of custom device trees is not supported for the Jetson Xavier family of devices in balenaOS. U-Boot provides the complete set of functionality necessary for loading custom device-trees in balenaOS for the Jetson Nano and TX2 devices, and this bootloader is not supported by the Jetson AGX Xavier and Jetson Xavier NX BSP. The Jetson AGX Orin family of devices uses a new Tegra UEFI bootloader which allows balenaOS to load custom device-trees.

To test a custom device tree on a Jetson Nano, TX2 or Jetson AGX Orin or Orin NX device, place your custom compiled device tree in the host operating system of your device, in the following path: `/mnt/sysroot/active/current/boot/` After that, navigate to the `Device Configuration` tab in the balenaCloud dashboard, activate the following configuration with the description `Define the file name of the DTB to be used`, and specify the file name of the custom device tree. The value of this configuration should contain the file name only. After the change is applied, the device will automatically reboot and load the new device tree.

After the custom device tree has been validated, it can be included in newer balenaOS images. For Jetson TX2 and Nano, open a pull request in the [balena Jetson device](https://github.com/balena-os/balena-jetson) repository following this [example commit](https://github.com/balena-os/balena-jetson/commit/3dbf9c96e5986c2138f318d1ee9f0d5c1a2fc3c8). For Jetson Orin devices, the PR should be opened in the [balena Jetson Orin](https://github.com/balena-os/balena-jetson-orin) repository. Once your PR is approved and merged, a new balenaOS image that includes your custom device tree will become available shortly.

Please note that if the changes for your carrier board expand past kernel device-trees, or require modifications to board configuration files like pin multiplexing configuration files or any other device-trees or files used by firmware, these may not be provided by the existing cloud images. During provisioning the resulting configuration changes are stored in the QSPI or in the hardware defined boot partitions, and thus will be replaced with the default values when updating the Host Operating System. Please [contact us](https://www.balena.io/contact-sales) if you would like to use a Jetson carrier board which may not be fully compatible with its' corresponding devkit, or with any of our cloud images for your Jetson module.

#### Configurable fan profiles

Jetson Orin Devices running balenaOS revisions newer than v6.1.24 and supervisor versions greater than v16.10.0 offer support for configurable fan profiles. You can switch between the options provided by Jetpack by navigating to the Device/Fleet Configuration tab on the sidebar of the balenaCloud dashboard, clicking "activate" on the "Define the device fan profile" configuration option, and typing in the desired value. The input value should be a string, without quotes. The change will be applied at runtime and will not trigger a device reboot. Preloading the [fan profile configuration](/reference/os/configuration#fan) before provisioning your device can be achieved by editing the [config.json](https://docs.balena.io/learn/develop/hardware/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json) file.

#### Configurable power modes

Jetson Orin Devices running balenaOS revisions newer than v6.1.24 and supervisor versions greater than v16.10.0 also offer the possibility for selecting the desired power mode. You can set the values *low*, *mid* and *high* or specify the power mode ID directly by navigating to the Device/Fleet Configuration tab on the sidebar of the balenaCloud dashboard, clicking "activate" on the "Define the device power mode" configuration option, and typing in the desired value. The input value should be a string, or a single digit number, without quotes. Please note that your device(s) will automatically reboot to apply the new power mode. The available power modes IDs for your device type are visible in the host OS in `/etc/nvpmodel.conf`. Preloading the desired power mode configuration can be achieved by editing the [config.json](https://docs.balena.io/learn/develop/hardware/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json) file and specifying the desired [power mode](/reference/os/configuration#power) before provisioning the device.

#### Container packages

The Jetson specific packages installed in your container images need to be in sync with the Linux for Tegra version used by the Host Operating System. Our base images for Jetson devices come pre-populated with `/etc/apt/sources.list.d/nvidia.list` files, which include the necessary links so that the apt repositories are in sync with the L4T version used by our latest OS images. If you suspect you encountered a mismatch, please check the `L4T` version in your Host OS using `uname -r` and compare it to the release version in your container's `/etc/apt/sources.list.d/nvidia.list` file. Please check our [Jetson Examples](https://github.com/balena-io-examples/jetson-examples) repository for more information on how to set-up your container images.

### iMX8 Devices

#### Custom device-trees

Loading of custom device trees in balenaOS for iMX boards is currently supported on the Variscite DART-MX8M Mini and Variscite VAR-SOM-MX8M-MINI Devkit.

To test your custom device tree, place it in the host operating system of your device in the following path: `/mnt/sysroot/active/current/boot/` . Then, navigate to the `Device Configuration` tab in the balenaCloud dashboard, activate the following configuration with the description `Define the file name of the DTB to be used`, and specify the file name of the custom device tree. The value of this configuration should contain the file name only. After the change is applied, the device will automatically reboot and load the new device tree.

After you have validated your custom device, it can be included in newer balenaOS images by opening a pull request in the [balena-variscite-mx8](https://github.com/balena-os/balena-variscite-mx8) repository. Once your PR is approved and merged, a new balenaOS image which includes your custom device tree will be made available shortly.


# Nvidia Jetson Orin


# Nvidia Jetson AGX Orin Devkit 32GB

<figure><img src="/files/M7XSht8uTJR1BMRQ9MiT" alt=""><figcaption></figcaption></figure>

The Nvidia Jetson AGX Orin 32GB development kit can be identified by the label printed on the inside bottom of the unit as shown. It mentions part number 975-13730-0000-000 but does not actually say 32GB.

<figure><img src="/files/g97iLF31oub9cElMNJZR" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/qejNJpCgNni3m5H2FndE" alt=""><figcaption></figcaption></figure>

This device exposes a debug UART interface over the microUSB port. From Linux machines, the serial connection can be accessed using `minicom -D /dev/ttyACM0`. It also offers one Display Port for video output.

The default internal storage used for provisioning balenaOS is the AGX Orin 32GB's on-board eMMC, and the [Jetson Flash](https://github.com/balena-os/jetson-flash) tool is used for provisioning balenaOS. The eMMC is the only boot medium supported for this device type currently.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

The debug UART interface of the Jetson AGX Orin 32GB Devkit is available through the micro-USB interface, when the device is powered on. Connect the other end of the micro-usb cable to your host/development PC. If your host is running Linux, the serial connection to the Jetson device can be accessed using `minicom -D /dev/ttyACM0`.

<figure><img src="/files/MUfyCE7L2iKTeBMTY7LR" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson AGX Orin Devkit 32GB to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>


# Nvidia Jetson AGX Orin Devkit 64GB

<figure><img src="/files/M7XSht8uTJR1BMRQ9MiT" alt=""><figcaption></figcaption></figure>

The Nvidia Jetson AGX Orin 64 GB development kit has a label on the inside bottom as shown. It mentions part number 945-13730-0050-000 and reads “Jetson AGX Orin 64GB Developer Kit”.

<figure><img src="/files/5PYQ06cEIzgJbmB37kJl" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/n8uerv1EPP9NEw8VGhJd" alt=""><figcaption></figcaption></figure>

This device exposes a debug UART interface over the microUSB port. From Linux machines, the serial connection can be accessed using `minicom -D /dev/ttyACM0`. It also offers one Display Port for video output.

The default internal storage used for provisioning balenaOS is the AGX Orin 64GB's on-board eMMC. If instead you would like to use an NVMe drive as main storage, please consult the OS installer [target\_devices](/reference/os/configuration#target_devices) configuration option or the [alternative provisioning options](#alternative-provisioning-options) section.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

The debug UART interface of the Jetson AGX Orin 64GB Devkit is available through the micro-USB interface, when the device is powered on. Connect the other end of the micro-usb cable to your host/development PC. If your host is running Linux, the serial connection to the Jetson device can be accessed using `minicom -D /dev/ttyACM0`.

<figure><img src="/files/MUfyCE7L2iKTeBMTY7LR" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson AGX Orin Devkit 64GB to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>

\
In case the UEFI firmware version on your device is older than v36.3.0, please update its firmware using the following guide:

* [Flashing Jetpack 6 using SDK Manager](https://developer.ridgerun.com/wiki/index.php/JetPack_6_Migration_and_Developer_Guide/Installing_JetPack_6/Flashing_with_SDK_Manager) 🔗

If for whatever reason checking the UEFI firmware version is not possible, flashing Jetpack 6 using the SDK Manager will guarantee your device has the latest firmware installed.

Once your device's UEFI firmware is v36.3.0 or newer, you can use a USB flash drive to provision it directly with balenaOS.

#### **Booting balenaOS flasher images from a USB flash drive**

If the firmware on your device is v36.3.0 or newer, inserting the USB flash drive with the balenaOS flasher image and connecting power to your device will provision the internal storage. In the unexpected event that your device does not boot the balenaOS flasher image from the attached USB flash drive automatically, use the following steps to manually select the USB flash drive for booting:

<details>

<summary>I want to use the debug UART interface</summary>

1. The debug UART interface of the Jetson AGX Orin 64GB Devkit is available through the micro-USB interface, when the device is powered on. Connect the other end of the micro-usb cable to your host/development PC. If your host is running Linux, the serial connection to the Jetson device can be accessed using `minicom -D /dev/ttyACM0`.

<figure><img src="/files/MUfyCE7L2iKTeBMTY7LR" alt=""><figcaption></figcaption></figure>

2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly.

<figure><img src="/files/hyiz9WzzmQG0nqG7nFU5" alt=""><figcaption></figcaption></figure>

If `Esc` was pressed, navigate to the Boot Manager Menu

<figure><img src="/files/yYcDq0P6RzveZ2LtNCnC" alt=""><figcaption></figcaption></figure>

3. Select the attached USB device as boot media

<figure><img src="/files/dGmIyiHCQxggQP4GHCVi" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Press the power button of your Jetson AGX Orin 64GB to initiate booting.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a keyboard and monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson AGX Orin Devkit 64GB to a monitor.**

1. Attach a USB keyboard and a monitor to the device.
2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly.

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/luYEWgjqrFYJx98A4n9L" alt=""><figcaption></figcaption></figure>

3. Select the attached USB flash drive as boot media:

<figure><img src="/files/7fzhigcGwxQgLqF0jaOA" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Press the power button of your Jetson AGX Orin 64GB to initiate booting.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

</details>

#### **Post-provisioning UEFI firmware update**

Once your device has been provisioned with balenaOS and powered back-on, it will attempt to update the UEFI firmware automatically. The status of the UEFI firmware update process is depicted by a progress bar on the debug UART interface, as well on the display, if connected.

{% hint style="warning" %}
Do not interrupt the UEFI firmware process by resetting or cutting power to the device.
{% endhint %}

If you are using the debug UART, the firmware update process will be displayed by a progress bar similar to the one below:

<figure><img src="/files/hxLCVkBYartrwdHelqXE" alt=""><figcaption></figcaption></figure>

If a display is connected to the device, the firmware update process will also be rendered on the screen:

<figure><img src="/files/iqcepQChgQ8fqTqXHVLE" alt=""><figcaption></figcaption></figure>

#### **Alternative provisioning options**

By default, most Jetson Orin devices need an internal storage media and a USB flash drive in order to be provisioned. The AGX Orin 64GB Devkit has a built-in eMMC which is used by default for provisioning balenaOS.

* If you would like to use a USB flash drive to flash an NVME drive attached to your Jetson AGX Orin 64GB instead of the on-board eMMC, use the [installer.target\_devices](/reference/os/configuration#target_devices) configuration option in the flasher USB drive's [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json) to specify the NVME as target medium:

```json
"installer": {
    "target_devices":"nvme0n1"
}
```

* If you would like the same USB flash drive or NVMe on which the balenaOS flasher image has been written to be used as both install and boot media, use both the [installer.migrate](/reference/os/configuration#migrate) and [installer.target\_devices](/reference/os/configuration#target_devices) configuration options:

```json
"installer": {
    "migrate": {
      "force": true
    },
    "target_devices":"sda nvme0n1"
}
```

The first medium found in the `target_devices` list will be used for provisioning and it will become the main storage of your device once flashing is complete.

Available target devices are:

* `mmcblk0` - on-board eMMC. Unless overriden, this is the default for the AGX Orin Devkit 64GB
* `sda` - removable drives like USB flash drives or SSDs
* `nvme0n1` - NVMe drive

<details>

<summary>How do I set this configuration in my balenaOS image?</summary>

1. Make sure you have [jq](https://jqlang.org/download/) and the [balena CLI](/reference/balena-cli/latest) installed on your host/development PC. You can obtain it from [here](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md).
2. Download the balenaOS image from the balenaCloud dashboard or use the balena CLI to obtain one:

```shell
balena os download jetson-agx-orin-devkit-64gb -o balena.img
```

3. Download a configuration file from your balenaCloud dashboard or generate a new one using the balena CLI:

```shell
balena config generate --fleet balena_cloud_org/balena_cloud_fleet --version 6.4.0 --network ethernet --appUpdatePollInterval 10 --output config.json
```

Replace `balena_cloud_org` and `balena_cloud_fleet` with your actual balena cloud organization and fleet.

4. Depending on your desired provisioning setup, set one or more of the available installer options:

```shell
tmp=$(mktemp)
jq '.installer.migrate.force |= true' config.json > ${tmp}
mv ${tmp} config.json
```

```shell
tmp=$(mktemp)
jq '.installer.target_devices |= "sda nvme0n1"' config.json > ${tmp}
mv ${tmp} config.json
```

5. Use the balena CLI to inject the modified configuration file in the newly downloaded image:

```shell
sudo balena config inject config.json -d balena.img
```

6. Write the balenaOS image (balena.img) to your USB flash drive or NVMe. We recommend using [Etcher](https://etcher.balena.io).
7. If your AGX Orin is powered on, press the power button and wait for the device to turn off.
8. Insert the freshly flashed USB flash drive or NVMe drive into the Jetson AGX Orin Devkit and press the power button.
9. Once provisioning is complete, the board will perform one of the following actions:

* restart and boot balenaOS automatically, if [installer.migrate.force](/reference/os/configuration#migrate) has been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json).
* shut down if [installer.migrate.force](/reference/os/configuration#migrate) has not been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json). Unplug the flasher USB flash drive before powering the AGX Orin Devkit back on.

10. Your device should appear in your application dashboard within a few minutes.

</details>


# Nvidia Jetson Orin Nano 8GB (SD) Devkit NVMe

<figure><img src="/files/sLCrnjms4KpYXkTrpI1V" alt=""><figcaption></figcaption></figure>

The Orin Nano 8GB SD module has the part number 900-13767-0050-000. This number may not be printed on some modules, however, the part can be distinguished by having an SD-CARD slot.

<figure><img src="/files/iOm4giQdnGOHVkN1hENQ" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/jeY7TbKsh52BpyJfDwIC" alt=""><figcaption></figcaption></figure>

The carrier board exposes a debug interface on the UART TXD, UART RXD and GND pins, which are located underneath the Orin module. Additionally, a monitor can be connected to the board's Display Port.

The default internal storage used for provisioning balenaOS on the Orin Nano 8GB (SD) Devkit is an NVMe drive, which needs to be attached to the carrier board prior to booting the flasher USB key. If instead you would like to use other media, like for example an SD card as main storage, please consult the OS installer [target\_devices](/reference/os/configuration#target_devices) configuration option or the [alternative provisioning options](#alternative-provisioning-options) section.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson Orin Nano to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>

\
In case the UEFI firmware version on your device is older than v36.3.0, please update its firmware by following any of the guides below:

* [Firmware update for Orin Nano SD-CARD](https://developer.nvidia.com/embedded/learn/get-started-jetson-orin-nano-devkit#firmware) 🔗
* [Flashing Jetpack 6 using SDK Manager](https://developer.ridgerun.com/wiki/index.php/JetPack_6_Migration_and_Developer_Guide/Installing_JetPack_6/Flashing_with_SDK_Manager) 🔗

If for whatever reason checking the UEFI firmware version is not possible, flashing Jetpack 6 using the SDK Manager will guarantee your device has the latest firmware installed.

Once your device's UEFI firmware is v36.3.0 or newer, you can use a USB flash drive to provision it directly with balenaOS.

#### **Booting balenaOS flasher images from a USB flash drive**

If the firmware on your device is v36.3.0 or newer, inserting the USB flash drive with the balenaOS flasher image and connecting power to your device will provision the internal storage. In the unexpected event that your device does not boot the balenaOS flasher image from the attached USB flash drive automatically, use the following steps to manually select the USB flash drive for booting:

<details>

<summary>I want to use the debug UART interface</summary>

1. For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/hyiz9WzzmQG0nqG7nFU5" alt=""><figcaption></figcaption></figure>

If `Esc` was pressed, navigate to the Boot Manager Menu:

<figure><img src="/files/yYcDq0P6RzveZ2LtNCnC" alt=""><figcaption></figcaption></figure>

3. Select the attached USB device as boot media:

<figure><img src="/files/dGmIyiHCQxggQP4GHCVi" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a keyboard and monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson Orin Nano to a monitor.**

1. Attach a USB keyboard and a monitor to the device.
2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/luYEWgjqrFYJx98A4n9L" alt=""><figcaption></figcaption></figure>

3. Select the attached USB flash drive as boot media:

<figure><img src="/files/7fzhigcGwxQgLqF0jaOA" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

</details>

#### **Post-provisioning UEFI firmware update**

Once your device has been provisioned with balenaOS and powered back-on, it will attempt to update the UEFI firmware automatically. The status of the UEFI firmware update process is depicted by a progress bar on the debug UART interface, as well on the display, if connected.

{% hint style="warning" %}
Do not interrupt the UEFI firmware process by resetting or cutting power to the device.
{% endhint %}

If you are using the debug UART, the firmware update process will be displayed by a progress bar similar to the one below:

<figure><img src="/files/hxLCVkBYartrwdHelqXE" alt=""><figcaption></figcaption></figure>

If a display is connected to the device, the firmware update process will also be rendered on the screen:

<figure><img src="/files/iqcepQChgQ8fqTqXHVLE" alt=""><figcaption></figcaption></figure>

#### **Alternative provisioning options**

By default, most Jetson Orin devices need an internal storage media and a USB flash drive in order to be provisioned. On the Jetson Orin Nano Devkit, an NVMe drive has to be attached to the carrier board before starting the provisioning process.

* If you would like to use a USB flash drive to flash an NVMe drive attached to your Jetson Orin Nano (SD) Devkit NVMe, simply insert the USB flash drive into your device and connect power to the board.
* If you would like the same SD-Card, USB flash drive or NVMe on which the balenaOS flasher image has been written to be used as both install and boot media, use both the [installer.migrate](/reference/os/configuration#migrate) and [installer.target\_devices](/reference/os/configuration#target_devices) configuration options:

```json
"installer": {
    "migrate": {
      "force": true
    },
    "target_devices":"mmcblk0 sda nvme0n1"
}
```

The first medium found in the `target_devices` list will be used for provisioning and it will become the main storage of your device once flashing is complete.

Available target devices are:

* `mmcblk0` - SD-CARD
* `sda` - removable drives like USB flash drives or SSDs
* `nvme0n1` - NVMe drive. Unless overriden, this is the default for the Jetson Orin Nano Devkit

<details>

<summary>How do I set this configuration in my balenaOS image?</summary>

1. Make sure you have [jq](https://jqlang.org/download/) and the [balena CLI](/reference/balena-cli/latest) installed on your host/development PC. You can obtain it from [here](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md).
2. Download the balenaOS image from the balenaCloud dashboard or use the balena CLI to obtain one:

```shell
balena os download jetson-orin-nano-devkit-nvme -o balena.img
```

3. Download a configuration file from your balenaCloud dashboard or generate a new one using the balena CLI:

```shell
balena config generate --fleet balena_cloud_org/balena_cloud_fleet --version 6.4.0 --network ethernet --appUpdatePollInterval 10 --output config.json
```

Replace `balena_cloud_org` and `balena_cloud_fleet` with your actual balena cloud organization and fleet.

4. Depending your desired provisioning setup, set one or more of the available installer options:

```shell
tmp=$(mktemp)
jq '.installer.migrate.force |= true' config.json > ${tmp}
mv ${tmp} config.json
```

```shell
tmp=$(mktemp)
jq '.installer.target_devices |= "mmcblk0 sda nvme0n1"' config.json > ${tmp}
mv ${tmp} config.json
```

5. Use the balena CLI to inject the modified configuration file in the newly downloaded image:

```shell
sudo balena config inject config.json -d balena.img
```

6. Write the balenaOS image (balena.img) to your SD-CARD, USB flash drive or NVMe. We recommend using [Etcher](https://etcher.balena.io).
7. Ensure the power cable is disconnected from the Orin Nano Devkit.
8. Insert the freshly flashed SD-CARD, USB flash drive or NVMe drive into the Devkit and connect its power cable.
9. Once provisioning is complete, the board will perform one of the following actions:
   * restart and boot balenaOS automatically, if [installer.migrate.force](/reference/os/configuration#migrate) has been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json).
   * shut down if [installer.migrate.force](/reference/os/configuration#migrate) has not been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json). Unplug the external flasher medium and then remove and re-connect the power cable to the Devkit.
10. Your device should appear in your application dashboard within a few minutes.

</details>


# Nvidia Jetson Orin Nano 8GB Production module

<figure><img src="/files/sLCrnjms4KpYXkTrpI1V" alt=""><figcaption></figcaption></figure>

The Orin Nano production module has the part number 900-13767-0030-000, which can be observed on the bottom. The main difference from the Orin Nano SD - 900-13767-0050-000 - is that it does not have an SD card slot. This module can be used with a Jetson Orin Nano Devkit carrier board, along with the balenaOS image for the Jetson Orin Nano 8GB (SD) Devkit, provided that the corresponding kernel device-tree is configured in your balena-cloud device configuration page.

<figure><img src="/files/SmU1HSbxDNDIPMzfwJCp" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/2UrIAqrUHW1JTrjkYVXS" alt=""><figcaption></figcaption></figure>

When this module is used with the carrier board provided by the Orin Nano Devkit, a debug interface is available on the UART TXD, UART RXD and GND pins, which are located underneath the Orin module. Additionally, a monitor can be connected to the board's Display Port.

The default internal storage used for provisioning balenaOS on the Orin Nano Production module is an NVMe drive, which needs to be attached to the carrier board prior to booting via a USB flash drive containing the balenaOS flasher image. If instead you would like to use other media, like for example an SSD as main storage, please consult the OS installer [target\_devices](/reference/os/configuration#target_devices) configuration option or the [alternative provisioning options](#alternative-provisioning-options) section.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson Orin Nano to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>

\
In case the UEFI firmware version on your device is older than v36.3.0, please update its firmware using the following guide:

* [Flashing Jetpack 6 using SDK Manager](https://developer.ridgerun.com/wiki/index.php/JetPack_6_Migration_and_Developer_Guide/Installing_JetPack_6/Flashing_with_SDK_Manager) 🔗

If for whatever reason checking the UEFI firmware version is not possible, flashing Jetpack 6 using the SDK Manager will guarantee your device has the latest firmware installed.

Once your device's UEFI firmware is v36.3.0 or newer, you can use a USB flash drive to provision it directly with balenaOS.

#### **Booting balenaOS flasher images from a USB flash drive**

If the firmware on your device is v36.3.0 or newer, inserting the USB flash drive with the balenaOS flasher image and connecting power to your device will provision the internal storage. In the unexpected event that your device does not boot the balenaOS flasher image from the attached USB flash drive automatically, use the following steps to manually select the USB flash drive for booting:

<details>

<summary>I want to use the debug UART interface</summary>

1. For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/hyiz9WzzmQG0nqG7nFU5" alt=""><figcaption></figcaption></figure>

If `Esc` was pressed, navigate to the Boot Manager Menu:

<figure><img src="/files/yYcDq0P6RzveZ2LtNCnC" alt=""><figcaption></figcaption></figure>

3. Select the attached USB device as boot media:

<figure><img src="/files/dGmIyiHCQxggQP4GHCVi" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive should be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a keyboard and monitor</summary>

**A Display Port cable or Display Port to HDMI adapter is necessary for connecting your Jetson Orin Nano to a monitor.**

1. Attach a USB keyboard and a monitor to the device.
2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/luYEWgjqrFYJx98A4n9L" alt=""><figcaption></figcaption></figure>

3. Select the attached USB flash drive as boot media:

<figure><img src="/files/7fzhigcGwxQgLqF0jaOA" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

</details>

#### **Post-provisioning UEFI firmware update**

Once your device has been provisioned with balenaOS and powered back-on, it will attempt to update the UEFI firmware automatically. The status of the UEFI firmware update process is depicted by a progress bar on the debug UART interface, as well on the display, if connected.

{% hint style="warning" %}
Please do not interrupt the UEFI firmware process by resetting or cutting power to the device.
{% endhint %}

If you are using the debug UART, the firmware update process will be displayed by a progress bar similar to the one below:

<figure><img src="/files/hxLCVkBYartrwdHelqXE" alt=""><figcaption></figcaption></figure>

If a display is connected to the device, the firmware update process will also be rendered on the screen:

<figure><img src="/files/iqcepQChgQ8fqTqXHVLE" alt=""><figcaption></figcaption></figure>

#### **Alternative provisioning options**

By default, most Jetson Orin devices need an internal storage media and a USB flash drive in order to be provisioned. When using the Jetson Orin Nano Devkit with a Jetson Orin Nano 8GB production module, an NVMe drive has to be attached to the carrier board before starting the provisioning process.

* If you would like to use a USB flash drive to flash an NVMe drive attached to your Jetson Orin Nano, simply insert the USB flash drive into your device and connect power to the board.
* If you would like the same SD-Card, USB flash drive or NVMe on which the balenaOS flasher image has been written to be used as both install and boot media, use both the [installer.migrate](/reference/os/configuration#migrate) and [installer.target\_devices](/reference/os/configuration#target_devices) configuration options:

```json
"installer": {
    "migrate": {
      "force": true
    },
    "target_devices":"mmcblk0 sda nvme0n1"
}
```

The first medium found in the `target_devices` list will be used for provisioning and it will become the main storage of your device once flashing is complete.

Available target devices are:

* `mmcblk0` - SD-CARD
* `sda` - removable drives like USB flash drives or SSDs
* `nvme0n1` - NVMe drive. Unless overriden, this is the default for the Jetson Orin Nano Devkit

<details>

<summary>How do I set this configuration in my balenaOS image?</summary>

1. Make sure you have [jq](https://jqlang.org/download/) and the [balena CLI](/reference/balena-cli/latest) installed on your host/development PC. You can obtain it from [here](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md).
2. Download the balenaOS image from the balenaCloud dashboard or use the balena CLI to obtain one:

```shell
balena os download jetson-orin-nano-devkit-nvme -o balena.img
```

3. Download a configuration file from your balenaCloud dashboard or generate a new one using the balena CLI:

```shell
balena config generate --fleet balena_cloud_org/balena_cloud_fleet --version 6.4.0 --network ethernet --appUpdatePollInterval 10 --output config.json
```

Replace `balena_cloud_org` and `balena_cloud_fleet` with your actual balena cloud organization and fleet.

4. Depending your desired provisioning setup, set one or more of the available installer options:

```shell
tmp=$(mktemp)
jq '.installer.migrate.force |= true' config.json > ${tmp}
mv ${tmp} config.json
```

```shell
tmp=$(mktemp)
jq '.installer.target_devices |= "mmcblk0 sda nvme0n1"' config.json > ${tmp}
mv ${tmp} config.json
```

5. Use the balena CLI to inject the modified configuration file in the newly downloaded image:

```shell
sudo balena config inject config.json -d balena.img
```

6. Write the balenaOS image (balena.img) to your SD-CARD, USB flash drive or NVMe. We recommend using [Etcher](https://etcher.balena.io).
7. Ensure the power cable is disconnected from the Orin Nano Devkit.
8. Insert the freshly flashed SD-CARD, USB flash drive or NVMe drive into the Devkit and connect its power cable.
9. Once provisioning is complete, the board will perform one of the following actions:
   * restart and boot balenaOS automatically, if [installer.migrate.force](/reference/os/configuration#migrate) has been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json).
   * shut down if [installer.migrate.force](/reference/os/configuration#migrate) has not been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json) Unplug the external flasher medium and then remove and re-connect the power cable to the Devkit.
10. Your device should appear in your application dashboard within a few minutes.

</details>


# Nvidia Jetson Orin NX 16GB in Xavier NX Devkit NVME

<figure><img src="/files/eWiDutS9v30havpJJYbZ" alt=""><figcaption></figcaption></figure>

Part number 900-13767-0000-000 is printed on the right side of the SOM bottom side, and can only be observed if the module is taken out of the devkit:

<figure><img src="/files/CCVTk0NNsdmjUoMDo1RA" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/BM9VfxfzzCsioWQ0zWxj" alt=""><figcaption></figcaption></figure>

The Jetson Orin NX 16GB module can be used with the Xavier NX Devkit, which exposes a debug interface on the UART TXD, UART RXD and GND pins. The UART pins are located underneath the Orin NX module. Additionally, a monitor can be connected to the board's HDMI port.

The default internal storage used for provisioning balenaOS on the Jetson Orin NX 16GB is an NVME drive, which needs to be attached to the carrier board prior to booting via a USB flash drive containing the balenaOS flasher image. If instead you would like to use other media, like for example an SSD as main storage, please consult the OS installer [target\_devices](/reference/os/configuration#target_devices) configuration option or the [alternative provisioning options](#alternative-provisioning-options) section.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**An HDMI cable is necessary for connecting your Jetson Orin NX to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>

\
In case the UEFI firmware version on your device is older than v36.3.0, please update its firmware using the following guide:

* [Flashing Jetpack 6 using SDK Manager](https://developer.ridgerun.com/wiki/index.php/JetPack_6_Migration_and_Developer_Guide/Installing_JetPack_6/Flashing_with_SDK_Manager) 🔗

If for whatever reason checking the UEFI firmware version is not possible, flashing Jetpack 6 using the SDK Manager will guarantee your device has the latest firmware installed.

Once your device's UEFI firmware is v36.3.0 or newer, you can use a USB flash drive to provision it directly with balenaOS.

#### **Booting balenaOS flasher images from a USB flash drive**

If the firmware on your device is v36.3.0 or newer, inserting the USB flash drive with the balenaOS flasher image and connecting power to your device will provision the internal storage. In the unexpected event that your device does not boot the balenaOS flasher image from the attached USB flash drive automatically, use the following steps to manually select the USB flash drive for booting:

<details>

<summary>I want to use the debug UART interface</summary>

1. For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/hyiz9WzzmQG0nqG7nFU5" alt=""><figcaption></figcaption></figure>

If `Esc` was pressed, navigate to the Boot Manager Menu:

<figure><img src="/files/yYcDq0P6RzveZ2LtNCnC" alt=""><figcaption></figcaption></figure>

3. Select the attached USB device as boot media:

<figure><img src="/files/dGmIyiHCQxggQP4GHCVi" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a keyboard and monitor</summary>

**An HDMI cable is necessary for connecting your Jetson Orin NX to a monitor.**

1. Attach a USB keyboard and a monitor to the device.
2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/luYEWgjqrFYJx98A4n9L" alt=""><figcaption></figcaption></figure>

3. Select the attached USB flash drive as boot media:

<figure><img src="/files/7fzhigcGwxQgLqF0jaOA" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

</details>

#### **Post-provisioning UEFI firmware update**

Once your device has been provisioned with balenaOS and powered back-on, it will attempt to update the UEFI firmware automatically. The status of the UEFI firmware update process is depicted by a progress bar on the debug UART interface, as well on the display, if connected.

{% hint style="warning" %}
Please do not interrupt the UEFI firmware process by resetting or cutting power to the device.
{% endhint %}

If you are using the debug UART, the firmware update process will be displayed by a progress bar similar to the one below:

<figure><img src="/files/hxLCVkBYartrwdHelqXE" alt=""><figcaption></figcaption></figure>

If a display is connected to the device, the firmware update process will also be rendered on the screen:

<figure><img src="/files/iqcepQChgQ8fqTqXHVLE" alt=""><figcaption></figcaption></figure>

#### **Alternative provisioning options**

By default, most Jetson Orin devices need an internal storage media and a USB flash drive in order to be provisioned. When using the Jetson Orin NX in a Xavier NX Devkit, an NVMe drive has to be attached to the carrier board before starting the provisioning process.

* If you would like to use a USB flash drive an NVME drive attached to your device, simply insert the USB flash drive and connect power to the board.
* If you would like the same USB flash drive or NVMe on which the balenaOS flasher image has been written to be used as both install and boot media, use both the [installer.migrate](/reference/os/configuration#migrate) and [installer.target\_devices](/reference/os/configuration#target_devices) configuration options:

```json
"installer": {
    "migrate": {
      "force": true
    },
    "target_devices":"sda nvme0n1"
}
```

The first medium found in the `target_devices` list will be used and it will become the main storage of your device once flashing is complete.

Available target devices are:

* `sda` - removable drives like USB flash drives or SSDs
* `nvme0n1` - NVMe drive. Unless overriden, this option is the default for your device

<details>

<summary>How do I set this configuration in my balenaOS image?</summary>

1. Make sure you have [jq](https://jqlang.org/download/) and the [balena CLI](/reference/balena-cli/latest) installed on your host/development PC. You can obtain it from [here](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md).
2. Download the balenaOS image from the balenaCloud dashboard or use the balena CLI to obtain one.

```shell
balena os download jetson-orin-nx-xavier-nx-devkit -o balena.img
```

3. Download a configuration file from your balenaCloud dashboard or generate a new one using the balena CLI:

```shell
balena config generate --fleet balena_cloud_org/balena_cloud_fleet --version 6.4.0 --network ethernet --appUpdatePollInterval 10 --output config.json
```

Replace `balena_cloud_org` and `balena_cloud_fleet` with your actual balena cloud organization and fleet.

4. Depending your desired provisioning setup, set one or more of the available installer options:

```shell
tmp=$(mktemp)
jq '.installer.migrate.force |= true' config.json > ${tmp}
mv ${tmp} config.json
```

```shell
tmp=$(mktemp)
jq '.installer.target_devices |= "sda nvme0n1"' config.json > ${tmp}
mv ${tmp} config.json
```

5. Use the balena CLI to inject the modified configuration file in the newly downloaded image:

```shell
sudo balena config inject config.json -d balena.img
```

6. Write the balenaOS image (balena.img) to your USB flash drive or NVMe. We recommend using [Etcher](https://etcher.balena.io).
7. Ensure the power cable is disconnected from your device.
8. Insert the freshly flashed SD-CARD, USB flash drive or NVMe drive into the carrier board and connect its power cable.
9. Once provisioning is complete, the board will perform one of the following actions:
   * restart and boot balenaOS automatically, if [installer.migrate.force](/reference/os/configuration#migrate) has been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json).
   * shut down if [installer.migrate.force](/reference/os/configuration#migrate) has not been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json). Unplug the external flasher medium and then remove and re-connect the power cable to the carrier board.
10. Your device should appear in your application dashboard within a few minutes.

</details>


# Seeed reComputer J4012 Jetson Orin NX 16GB

<figure><img src="/files/u4CX2JppzW2ldVPF4gGP" alt=""><figcaption></figcaption></figure>

The device has the Seeed Studio logo on the back, and the following sticker on the bottom:

<figure><img src="/files/T5AGSWYNaN3qYsR2x0yA" alt=""><figcaption></figcaption></figure>

The SOM in the Seeed reComputer J4012 is a Jetson Orin NX 16GB, which has the part number 900-13767-0000-000. The J401 carrier board exposes a debug interface on the UART TXD, UART RXD and GND pins, which are located underneath the Orin NX SOM. Additionally, a monitor can be connected to the board's HDMI Port.

The default internal storage used for provisioning balenaOS on the Seeed reComputer J4012 Jetson Orin NX 16GB is an NVME drive, which needs to be attached to the carrier board prior to booting via a USB flash drive containing the balenaOS flasher image. If instead you would like to use other media, like for example an SSD as main storage, please consult the OS installer [target\_devices](/reference/os/configuration#target_devices) configuration option or the [alternative provisioning options](#alternative-provisioning-options) section.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**An HDMI cable is necessary for connecting your Seed reComputer J4012 to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>

\
In case the UEFI firmware version on your device is older than v36.3.0, please update its firmware using the following guide:

* [Flashing Jetpack 6 using SDK Manager](https://developer.ridgerun.com/wiki/index.php/JetPack_6_Migration_and_Developer_Guide/Installing_JetPack_6/Flashing_with_SDK_Manager) 🔗

If for whatever reason checking the UEFI firmware version is not possible, flashing Jetpack 6 using the SDK Manager will guarantee your device has the latest firmware installed.

Once your device's UEFI firmware is v36.3.0 or newer, you can use a USB flash drive to provision it directly with balenaOS.

#### **Booting balenaOS flasher images from a USB flash drive**

If the firmware on your device is v36.3.0 or newer, inserting the USB flash drive with the balenaOS flasher image and connecting power to your device will provision the internal storage. In the unexpected event that your device does not boot the balenaOS flasher image from the attached USB flash drive automatically, use the following steps to manually select the USB flash drive for booting:

<details>

<summary>I want to use the debug UART interface</summary>

1. For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/hyiz9WzzmQG0nqG7nFU5" alt=""><figcaption></figcaption></figure>

If `Esc` was pressed, navigate to the Boot Manager Menu:

<figure><img src="/files/yYcDq0P6RzveZ2LtNCnC" alt=""><figcaption></figcaption></figure>

3. Select the attached USB device as boot media:

<figure><img src="/files/dGmIyiHCQxggQP4GHCVi" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a keyboard and monitor</summary>

**An HDMI cable is necessary for connecting your Seeed reComputer J4012 to a monitor.**

1. Attach a USB keyboard and a monitor to the device.
2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/luYEWgjqrFYJx98A4n9L" alt=""><figcaption></figcaption></figure>

3. Select the attached USB flash drive as boot media:

<figure><img src="/files/7fzhigcGwxQgLqF0jaOA" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

</details>

#### **Post-provisioning UEFI firmware update**

Once your device has been provisioned with balenaOS and powered back-on, it will attempt to update the UEFI firmware automatically. The status of the UEFI firmware update process is depicted by a progress bar on the debug UART interface, as well on the display, if connected.

{% hint style="warning" %}
Do not interrupt the UEFI firmware process by resetting or cutting power to the device.
{% endhint %}

If you are using the debug UART, the firmware update process will be displayed by a progress bar similar to the one below:

<figure><img src="/files/hxLCVkBYartrwdHelqXE" alt=""><figcaption></figcaption></figure>

If a display is connected to the device, the firmware update process will also be rendered on the screen:

<figure><img src="/files/iqcepQChgQ8fqTqXHVLE" alt=""><figcaption></figcaption></figure>

#### **Alternative provisioning options**

By default, most Jetson Orin devices need an internal storage media and a USB flash drive in order to be provisioned. When using the Seeed reComputer J4012, an NVMe drive has to be attached to the carrier board before starting the provisioning process.

* If you would like to use a USB flash drive an NVME drive attached to your device, simply insert the USB flash drive and connect power to the board.
* If you would like the same USB flash drive or NVMe on which the balenaOS flasher image has been written to be used as both install and boot media, use both the [installer.migrate](/reference/os/configuration#migrate) and [installer.target\_devices](/reference/os/configuration#target_devices) configuration options:

```json
"installer": {
    "migrate": {
      "force": true
    },
    "target_devices":"sda nvme0n1"
}
```

The first medium found in the `target_devices` list will be used and it will become the main storage of your device once flashing is complete.

Available target devices are:

* `sda` - removable drives like USB flash drives or SSDs
* `nvme0n1` - NVMe drive. Unless overriden, this option is the default for your device

<details>

<summary>How do I set this configuration in my balenaOS image?</summary>

1. Make sure you have [jq](https://jqlang.org/download/) and the [balena CLI](/reference/balena-cli/latest) installed on your host/development PC. You can obtain it from [here](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md).
2. Download the balenaOS image from the balenaCloud dashboard or use the balena CLI to obtain one.

```shell
balena os download jetson-orin-nx-seeed-j4012 -o balena.img
```

3. Download a configuration file from your balenaCloud dashboard or generate a new one using the balena CLI:

```shell
balena config generate --fleet balena_cloud_org/balena_cloud_fleet --version 6.4.0 --network ethernet --appUpdatePollInterval 10 --output config.json
```

Replace `balena_cloud_org` and `balena_cloud_fleet` with your actual balena cloud organization and fleet.

4. Depending your desired provisioning setup, set one or more of the available installer options:

```shell
tmp=$(mktemp)
jq '.installer.migrate.force |= true' config.json > ${tmp}
mv ${tmp} config.json
```

```shell
tmp=$(mktemp)
jq '.installer.target_devices |= "sda nvme0n1"' config.json > ${tmp}
mv ${tmp} config.json
```

5. Use the balena CLI to inject the modified configuration file in the newly downloaded image:

```shell
sudo balena config inject config.json -d balena.img
```

6. Write the balenaOS image (balena.img) to your USB flash drive or NVMe. We recommend using [Etcher](https://etcher.balena.io).
7. Ensure the power cable is disconnected from your device.
8. Insert the freshly flashed SD-CARD, USB flash drive or NVMe drive into the carrier board and connect its power cable.
9. Once provisioning is complete, the board will perform one of the following actions:
   * restart and boot balenaOS automatically, if [installer.migrate.force](/reference/os/configuration#migrate) has been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json).
   * shut down if [installer.migrate.force](/reference/os/configuration#migrate) has not been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json). Unplug the external flasher medium and then remove and re-connect the power cable to the carrier board.
10. Your device should appear in your application dashboard within a few minutes.

</details>


# Seeed reComputer J3010 Jetson Orin Nano 4GB

The device has the Seeed Studio logo on the back, and the following sticker on the bottom:

<figure><img src="/files/2rRF1rNG2I7nZfeFObAQ" alt=""><figcaption></figcaption></figure>

The SOM in the Seeed reComputer J3010 is a Jetson Orin Nano 4GB, which has the part number 900-13767-0040-000. This part number can be found on the bottom of the SOM, if it is taken out of the carrier board:

<figure><img src="/files/ctCxESifJ9IsrpQVKFgT" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/lHpBUEpBZjJcXkzRTv9T" alt=""><figcaption></figcaption></figure>

The J401 carrier board included in the full reComputer J3010 system exposes a debug interface on the UART TXD, UART RXD and GND pins, which are located underneath the Orin Nano SOM. Additionally, a monitor can be connected to the board's HDMI Port.

The default internal storage used for provisioning balenaOS on the Seeed reComputer J3010 Jetson Orin Nano 4GB is an NVME drive, which needs to be attached to the carrier board prior to booting via a USB flash drive containing the balenaOS flasher image. If instead you would like to use other media, like for example an SSD as main storage, please consult the OS installer [target\_devices](/reference/os/configuration#target_devices) configuration option or the [alternative provisioning options](#alternative-provisioning-options) section below.

#### **Checking your Jetson Orin's UEFI firmware version**

You can check which UEFI firmware version your Jetson Orin device is running either by connecting to your device's debug UART interface, or by attaching a display to the Orin's video port.

<details>

<summary>I want to use the debug UART interface</summary>

For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

If you are using the UART interface, the UEFI firmware version will be printed in the boot sequence logs:

<figure><img src="/files/t3PTpnZZNMUyYB7O2ABG" alt=""><figcaption></figcaption></figure>

Alternatively, if booting is stopped in the UEFI menu by pressing `Esc`, the firmware version will be printed in the top-left corner:

<figure><img src="/files/hzckSWWFjWBjlJX47R00" alt=""><figcaption></figcaption></figure>

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a monitor</summary>

**An HDMI cable is necessary for connecting your Seed reComputer J3010 to a monitor.** Once the monitor is attached, the UEFI firmware version will be displayed at the top of the screen:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

</details>

\
In case the UEFI firmware version on your device is older than v36.3.0, please update its firmware using the following guide:

* [Flashing Jetpack 6 using SDK Manager](https://developer.ridgerun.com/wiki/index.php/JetPack_6_Migration_and_Developer_Guide/Installing_JetPack_6/Flashing_with_SDK_Manager) 🔗

If for whatever reason checking the UEFI firmware version is not possible, flashing Jetpack 6 using the SDK Manager will guarantee your device has the latest firmware installed.

Once your device's UEFI firmware is v36.3.0 or newer, you can use a USB flash drive to provision it directly with balenaOS.

#### **Booting balenaOS flasher images from a USB flash drive**

If the firmware on your device is v36.3.0 or newer, inserting the USB flash drive with the balenaOS flasher image and connecting power to your device will provision the internal storage. In the unexpected event that your device does not boot the balenaOS flasher image from the attached USB flash drive automatically, use the following steps to manually select the USB flash drive for booting:

<details>

<summary>I want to use the debug UART interface</summary>

1. For this step you will need a USB to TTL converter cable. The USB to TTL converter's pins need to be connected to the UART TXD, UART RXD and GND pins on the Jetson carrier board, which are located underneath the Orin module. The other end of the cable should be plugged into the USB port of your host/development PC. Your host PC can connect to the Jetson device using a serial communication program like `minicom`

<figure><img src="/files/TgZRpOxbbiSZfwKQ2blv" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZY2f11gCZSssdOWIrGjY" alt=""><figcaption></figcaption></figure>

2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/hyiz9WzzmQG0nqG7nFU5" alt=""><figcaption></figcaption></figure>

If `Esc` was pressed, navigate to the Boot Manager Menu:

<figure><img src="/files/yYcDq0P6RzveZ2LtNCnC" alt=""><figcaption></figcaption></figure>

3. Select the attached USB device as boot media:

<figure><img src="/files/dGmIyiHCQxggQP4GHCVi" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

If instead you would like to use a monitor and a keyboard, please expand the section below.

</details>

<details>

<summary>I want to use a keyboard and monitor</summary>

**An HDMI cable is necessary for connecting your Seeed reComputer to a monitor.**

1. Attach a USB keyboard and a monitor to the device.
2. Power on the device and press `Esc` when prompted by the UEFI firmware, or `F11` to enter the Boot Manager Menu directly:

<figure><img src="/files/jQEzFzSnbq9bK9mwNKE8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/luYEWgjqrFYJx98A4n9L" alt=""><figcaption></figcaption></figure>

3. Select the attached USB flash drive as boot media:

<figure><img src="/files/7fzhigcGwxQgLqF0jaOA" alt=""><figcaption></figcaption></figure>

4. Your device should boot from the attached USB flash drive and provision the internal storage. Once provisioning is complete and the device shuts down, the USB flash drive can be unplugged.
5. Remove and re-connect power to the carrier board.
6. Your device should appear in your application dashboard within a few minutes.

Should you encounter any unexpected issues while provisioning your device, please follow the instructions for our [Jetson Flash](https://github.com/balena-os/jetson-flash) tool to flash your device in recovery boot mode.

</details>

#### **Post-provisioning UEFI firmware update**

Once your device has been provisioned with balenaOS and powered back-on, it will attempt to update the UEFI firmware automatically. The status of the UEFI firmware update process is depicted by a progress bar on the debug UART interface, as well on the display, if connected.

{% hint style="warning" %}
Do not interrupt the UEFI firmware process by resetting or cutting power to the device.
{% endhint %}

If you are using the debug UART, the firmware update process will be displayed by a progress bar similar to the one below:

<figure><img src="/files/hxLCVkBYartrwdHelqXE" alt=""><figcaption></figcaption></figure>

If a display is connected to the device, the firmware update process will also be rendered on the screen:

<figure><img src="/files/iqcepQChgQ8fqTqXHVLE" alt=""><figcaption></figcaption></figure>

#### **Alternative provisioning options**

By default, most Jetson Orin devices need an internal storage media and a USB flash drive in order to be provisioned. When using the Seeed reComputer J3010, an NVMe drive has to be attached to the carrier board before starting the provisioning process.

* If you would like to use a USB flash drive an NVME drive attached to your device, simply insert the USB flash drive and connect power to the board.
* If you would like the same USB flash drive or NVMe on which the balenaOS flasher image has been written to be used as both install and boot media, use both the [installer.migrate](/reference/os/configuration#migrate) and [installer.target\_devices](/reference/os/configuration#target_devices) configuration options:

```json
"installer": {
    "migrate": {
      "force": true
    },
    "target_devices":"sda nvme0n1"
}
```

The first medium found in the `target_devices` list will be used and it will become the main storage of your device once flashing is complete.

Available target devices are:

* `sda` - removable drives like USB flash drives or SSDs
* `nvme0n1` - NVMe drive. Unless overriden, this option is the default for your device

<details>

<summary>How do I set this configuration in my balenaOS image?</summary>

1. Make sure you have [jq](https://jqlang.org/download/) and the [balena CLI](/reference/balena-cli/latest) installed on your host/development PC. You can obtain it from [here](https://github.com/balena-io/balena-cli/blob/master/INSTALL.md).
2. Download the balenaOS image from the balenaCloud dashboard or use the balena CLI to obtain one.

```shell
balena os download jetson-orin-nano-seeed-j3010 -o balena.img
```

3. Download a configuration file from your balenaCloud dashboard or generate a new one using the balena CLI:

```shell
balena config generate --fleet balena_cloud_org/balena_cloud_fleet --version 6.4.0 --network ethernet --appUpdatePollInterval 10 --output config.json
```

Replace `balena_cloud_org` and `balena_cloud_fleet` with your actual balena cloud organization and fleet.

4. Depending your desired provisioning setup, set one or more of the available installer options:

```shell
tmp=$(mktemp)
jq '.installer.migrate.force |= true' config.json > ${tmp}
mv ${tmp} config.json
```

```shell
tmp=$(mktemp)
jq '.installer.target_devices |= "sda nvme0n1"' config.json > ${tmp}
mv ${tmp} config.json
```

5. Use the balena CLI to inject the modified configuration file in the newly downloaded image:

```shell
sudo balena config inject config.json -d balena.img
```

6. Write the balenaOS image (balena.img) to your USB flash drive or NVMe. We recommend using [Etcher](https://etcher.balena.io).
7. Ensure the power cable is disconnected from your device.
8. Insert the freshly flashed SD-CARD, USB flash drive or NVMe drive into the carrier board and connect its power cable.
9. Once provisioning is complete, the board will perform one of the following actions:
   * restart and boot balenaOS automatically, if [installer.migrate.force](/reference/os/configuration#migrate) has been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json).
   * shut down if [installer.migrate.force](/reference/os/configuration#migrate) has not been set in [config.json](https://docs.balena.io/learn/develop/hardware/jetson-orin/pages/LdQx2ccjhF5sXnDK5Nt6#about-config.json). Unplug the external flasher medium and then remove and re-connect the power cable to the carrier board.
10. Your device should appear in your application dashboard within a few minutes.

</details>


# Provision with Cloud IoT


# Cloud IoT Provisioning with AWS

The [AWS IoT](https://aws.amazon.com/iot) platform provides a valuable suite of services to collect, store, and distribute IoT data and actions. Its [IoT Core](https://aws.amazon.com/iot-core) service is the portal for registration and messaging with Internet-connected things. We want to make it easy for balena devices to register and interact with IoT Core.

Our IoT provisioning tools automate device registration to AWS IoT Core, and leverage balenaCloud and environment variables to store and access the registration credentials. This guide shows you how provisioning works and gets you started with the tools in the [aws-iot-provision](https://github.com/balena-io-examples/aws-iot-provision) repository.

## How It Works

Provisioning includes three components:

* **Service Container** like [Cloud Relay block](https://github.com/balena-io-examples/cloud-relay) on a device to request the provisioning and use the credential environment variables from balenaCloud
* **Lambda (cloud) function** to securely validate device identity and register the device with IoT Core, triggered by an HTTP request ([source code](https://github.com/balena-io-examples/aws-iot-provision/blob/master/index.js))
* **balenaCloud** to accept and store the generated key/certificate credentials for the device

The cloud function first validates the device UUID in the provision request with balenaCloud. Then it generates a public key certificate and registers with the IoT Core service. The function then provides the generated credentials to balenaCloud, which stores and pushes them to the device as environment variables for use by the service container.

In addition to registration, Cloud Relay block makes it easy to send data to AWS. It integrates with balena's block [ecosystem](https://hub.balena.io/blocks) for application development and messaging. So you only need to send your data to an MQTT container on the device, and the block handles all of the interaction with IoT Core.

**Note:** A service container like Cloud Relay on the device is not *required* to send the provisioning request. You may call the cloud function HTTP endpoint from your compute infrastructure to pre-generate the key/certificate for the cloud. However, the device must be registered already with balenaCloud.

## Getting Started

The tools described here automate *per-device* integration with AWS. However, first you must complete some initial one-time configuration on your AWS account. See the [AWS setup](https://github.com/balena-io-examples/aws-iot-provision/#setup-and-testing) section of the provisioning repo documentation for details.

## Create, Deploy, and Test Lambda function

The provisioning tools set up the Lambda function itself as well as a `provision` HTTP endpoint to request provisioning based on a device's UUID. The [workspace setup](https://github.com/balena-io-examples/aws-iot-provision/#workspace-setup) section of the documentation walks you through creation of this Lambda function and HTTP endpoint, including:

* configuration of the tools for testing and deployment
* testing the function locally
* deployment to AWS and end-to-end testing

The result is a functioning HTTP endpoint on AWS, ready for provisioning requests.

## Try a Tutorial

We created a blog post [tutorial](https://www.balena.io/blog/introducing-cloud-relay-block-send-data-to-cloud-provider/) on device provisioning with AWS IoT and use of Cloud Relay block to send system metrics data. The tutorial also shows how to route data sent to IoT Core on to Cloudwatch for graphing.


# Cloud IoT Provisioning with Azure

The [Azure IoT](https://docs.microsoft.com/en-us/azure/iot-fundamentals/) platform provides a valuable suite of services to collect, store, and distribute IoT data and actions. Its [IoT Hub](https://docs.microsoft.com/en-us/azure/iot-hub/iot-concepts-and-iot-hub) service is the portal for registration and messaging with Internet-connected things. We want to make it easy for balena devices to register and interact with IoT Hub.

Our IoT provisioning tools automate device registration to Azure IoT Hub, and leverage balenaCloud and environment variables to store and access the registration credentials. This guide shows you how provisioning works and gets you started with the tools in the [azure-iot-provision](https://github.com/balena-io-examples/azure-iot-provision) repository.

## How It Works

Provisioning includes three components:

* **Service Container** like [Cloud Relay block](https://github.com/balena-io-examples/cloud-relay) on a device to request the provisioning and use the credential environment variables from balenaCloud
* **Azure (cloud) function** to securely validate device identity and register the device with IoT Hub, triggered by an HTTP request ([source code](https://github.com/balena-io-examples/azure-iot-provision/blob/master/index.js))
* **balenaCloud** to accept and store the generated key/certificate credentials for the device

The cloud function first validates the device UUID in the provision request with balenaCloud. Then it generates a public key certificate and registers with the IoT Hub service. The function then provides the generated credentials to balenaCloud, which stores and pushes them to the device as environment variables for use by the service container.

In addition to registration, Cloud Relay block makes it easy to send data to Azure. It integrates with balena's block [ecosystem](https://hub.balena.io/blocks) for application development and messaging. So you only need to send your data to an MQTT container on the device, and the block handles all of the interaction with IoT Hub.

**Note:** A service container like Cloud Relay on the device is not *required* to send the provisioning request. You may call the cloud function HTTP endpoint from your compute infrastructure to pre-generate the key/certificate for the cloud. However, the device must be registered already with balenaCloud.

## Getting Started

The tools described here automate *per-device* integration with Azure. However, first you must complete some initial one-time configuration on your Azure account. See the [Azure setup](https://github.com/balena-io-examples/azure-iot-provision/#setup-and-testing) section of the provisioning repo documentation for details.

## Create, Deploy, and Test Azure function

The provisioning tools set up the Azure function itself as well as a `provision` HTTP endpoint to request provisioning based on a device's UUID. The [workspace setup](https://github.com/balena-io-examples/azure-iot-provision/#workspace-setup) section of the documentation walks you through creation of this Azure function and HTTP endpoint, including:

* configuration of the tools for testing and deployment
* testing the function locally
* deployment to Azure and end-to-end testing

The result is a functioning HTTP endpoint on Azure, ready for provisioning requests.

## Try a Tutorial

We created a blog post [tutorial](https://www.balena.io/blog/introducing-cloud-relay-block-send-data-to-cloud-provider/) on device provisioning with AWS IoT and use of Cloud Relay block to send system metrics data. The tutorial also shows how to route data sent to IoT Core on to Cloudwatch for graphing.


# Cloud IoT Provisioning with ClearBlade-GCP

The [ClearBlade-GCP IoT](https://www.clearblade.com/iot-core/) platform provides a valuable suite of services to collect, store, and distribute IoT data and actions. Its [IoT Core](https://iot.clearblade.com/iot-core) service is the portal for registration and messaging with Internet-connected things. We want to make it easy for balena devices to register and interact with IoT Core.

Our IoT provisioning tools automate device registration to ClearBlade IoT Core, and leverage balenaCloud and environment variables to store and access the registration credentials. This guide shows you how provisioning works and gets you started with the tools in the [cb-gcp-iot-provision](https://github.com/balena-io-examples/cb-gcp-iot-provision) repository.

As its name suggests, is a hybrid platform. provides the IoT Core service, while Google Cloud (GCP) provides the underlying host platform for other services like the cloud function described below.

## How It Works

Provisioning includes three components:

* **Service Container** like [Cloud Relay block](https://github.com/balena-io-examples/cloud-relay) on a device to request the provisioning and use the credential environment variables from balenaCloud
* **Cloud function** to securely validate device identity and register the device with IoT Core, triggered by an HTTP request ([source code](https://github.com/balena-io-examples/cb-gcp-iot-provision/blob/master/index.js))
* **balenaCloud** to accept and store the generated key/certificate credentials for the device

The cloud function first validates the device UUID in the provision request with balenaCloud. Then it generates a public key pair and registers with the IoT Core service. The function then provides the generated credentials to balenaCloud, which stores and pushes them to the device as environment variables for use by the service container.

In addition to registration, Cloud Relay block makes it easy to send data to ClearBlade-GCP. It integrates with balena's block [ecosystem](https://hub.balena.io/blocks) for application development and messaging. So you only need to send your data to an MQTT container on the device, and the block handles all of the interaction with IoT Core.

**Note:** A service container like Cloud Relay on the device is not *required* to send the provisioning request. You may call the cloud function HTTP endpoint from your compute infrastructure to pre-generate the key/certificate for the cloud. However, the device must be registered already with balenaCloud.

## Getting Started

The tools described here automate *per-device* integration with ClearBlade-GCP. However, first you must complete some initial one-time configuration on your ClearBlade account. See the [ClearBlade setup](https://github.com/balena-io-examples/cb-gcp-iot-provision/#setup-and-testing) section of the provisioning repo documentation for details.

## Create, Deploy, and Test Cloud function

The provisioning tools set up the Cloud function itself as well as a `provision` HTTP endpoint to request provisioning based on a device's UUID. The [workspace setup](https://github.com/balena-io-examples/cb-gcp-iot-provision/#workspace-setup) section of the documentation walks you through creation of this Cloud function and HTTP endpoint, including:

* configuration of the tools for testing and deployment
* testing the function locally
* deployment to GCP and end-to-end testing

The result is a functioning HTTP endpoint on GCP, ready for provisioning requests.

## Try a Tutorial

We created a blog post [tutorial](https://www.balena.io/blog/introducing-cloud-relay-block-send-data-to-cloud-provider/) on device provisioning with AWS IoT and use of Cloud Relay block to send system metrics data. The tutorial also shows how to route data sent to IoT Core on to Cloudwatch for graphing.


# Deploy


# Deploy to your Fleet

On balenaCloud, when we deploy code to devices grouped in a fleet, they all run what we refer to as a "release". A release consists of a Docker image or set of images on our registry. These images are built from a source code repository, either locally or remotely on the [balenaCloud build server](#the-balenacloud-build-server). When a successful release is created, all devices in the fleet are instructed to download and run the new release (according to the chosen [update strategy](/learn/deploy/release-strategy/update-strategies)).

There are 3 ways to create and deploy a release, namely [balena push](#balena-push), [balena deploy](#balena-build--deploy) and [git push](#git-push). Each method has slightly different use cases and differ on how and where the container images are built. We'll explain each of the options in more detail below. If you are just starting out with balenaCloud, we recommend using [balena push](#balena-push).

To get started with the balena CLI, check out our [balena CLI masterclass](/learn/more/masterclasses/cli-masterclass)

## Balena Push

### Overview

`balena push` is the recommended method for deployment and [development](/learn/develop/local-mode) on the balenaCloud platform. To use `balena push`you need to first [install the balena CLI](/reference/balena-cli/latest#installation) and ensure you are logged in to your account with`balena login`.

When you run the `balena push <APP_NAME or DEVICE_IP>` command from your laptop it will essentially take your project (or repository) folder, compress it and send it to the [balenaCloud build server](#the-balenacloud-build-server) or local balenaOS device in [localMode](/learn/develop/local-mode) where it will be built.

<figure><img src="/files/OtNIq71bUlccSvAWq5ge" alt=""><figcaption></figcaption></figure>

Once the cloud builder has successfully completed building all the images in the deployment, it will upload these images to the balenaCloud registry and create a release entry in the [balena API](/reference/api/overview) database. It will then notify all the devices in the fleet that a new release is available. If you need to pull in proprietary code or use a private base image during your builds, you can do so using the [build time secrets](#build-time-secrets-and-variables) or [private base images](#private-base-images) feature of `balena push`.

It should be noted that `balena push` is independent of git, so you are free to use any version control system you wish. This also means that it is possible to use [git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) in your project when deploying with `balena push`.

{% hint style="info" %}
Refer to the [`balena push` command reference](/reference/balena-cli/latest#push) for additional documentation.
{% endhint %}

## Balena Build & Deploy

### Overview

The `balena deploy` is functionally very similar to [balena push](#balena-push) but avoids pushing any source code to the [balenaCloud build server](#the-balenacloud-build-server). It gives more control over how and where your container images are built, allowing for `balena deploy` to be integrated into your own [CI/CD](https://en.wikipedia.org/wiki/Continuous_deployment) build system.

<figure><img src="/files/bmRM9MTAqfGhYHXIj3Q1" alt=""><figcaption></figcaption></figure>

With `balena build` container images are built on your development machine or on a remote machine, by specifying a docker daemon's IP address and port number with the relevant command-line options (for example a device running a balenaOS [development image](/reference/os/overview)). Depending on your fleet's targeted CPU architecture builds will be run emulated via [qemu](https://www.qemu.org/).

If you are building your own container images, `balena deploy` will upload the images to the balenaCloud image registry and then create a release entry in the [balena API](/reference/api/overview) database. The devices in the fleet will then be notified of a new release and download it. Should `balena deploy` not find the required images on the specified docker daemon, it will automatically trigger a build.

Like `balena push` it is also independent of git, and you can use any version control system you wish. It is also possible to use [private base images](#private-base-images).

{% hint style="info" %}
Refer to the [`balena build`](/reference/balena-cli/latest#build) and [`balena deploy` command reference](/reference/balena-cli/latest#deploy) for additional documentation.
{% endhint %}

## Git Push

### Overview

The `git push balena master` method of deployment is the original deployment mechanism for balenaCloud. While we continue to support git push, it is considered a legacy method for pushing code to a fleet, and if possible you should use [balena push](#balena-push) as it makes for a consistent workflow and methodology.

The `git push` workflow requires that you have [git](https://git-scm.com/) installed on your development machine and that you have an SSH key [setup on your balenaCloud account](/learn/manage/ssh-access).

<figure><img src="/files/J6Zoa2SA620ubbck4LFs" alt=""><figcaption></figcaption></figure>

Then, simply add your balenaCloud app's git endpoint to your local git repository via `git remote add balena <fleet git endpoint>` . You can find the fleet git remote endpoint by clicking the 'Add release' button in the releases tab of the dashboard.

<figure><img src="/files/ubwKBVM3KZt91ZRbZlnt" alt=""><figcaption></figcaption></figure>

Whenever you subsequently need to push code to your devices, simply run `git push balena master`.

{% hint style="warning" %}
The balenaCloud git repository **is not** intended as a code hosting solution, and we cannot guarantee the persistence of data in balenaCloud git remotes. We recommend you use a service like [GitHub](https://github.com/) to manage and share your code.
{% endhint %}

If you want to push a different local git branch to your balena fleet all you need to do is: `git push balena my-local-branch:master`

### Switching Between Apps

To completely change the code you have pushed to a fleet with `git` you will need to force a rewrite of the git remote endpoint's history. To do this, you just need to run the same command with the `-f` flag from the new project you wish to deploy. For example:

```shell
$ cd project/my-new-project
$ git push balena master -f
```

### Limitations

The `git push` workflow is a great way to deploy code, but it has a number of limitations when compared to `balena push` and `balena deploy`. One is mentioned above, where it is necessary to rewrite the history and force push to completely change the source code and build a new release from scratch.

Another is that it's not possible to use the [build time secrets](#build-time-secrets-and-variables) or [private base images](#private-base-images) without having to commit your secrets into your code repository.

In order to allow options like emulation and nocache, the `git push` workflow uses specifically named remote branches (see next section) however, this has the limitation that it is not possible to invalidate the cache of an emulated build pushed with `git push`.

#### Additional Options

Like `balena push` the `git push` workflow also allows triggering a build that invalidates the Docker layer cache and builds from scratch. This can be achieved by pushing to a special branch called `balena-nocache` as shown in the example below:

```shell
$ git push balena master:balena-nocache
```

Similarly you can also trigger a [qemu](https://www.qemu.org/) build on the [balenaCloud](#the-balenacloud-build-server) build server by pushing to the `balena-emulated` remote branch as shown below:

```shell
$ git push balena master:balena-emulated
```

## Project Structure

When deploying a balena project, the build system will try to build the most appropriate release for a specific set of devices. The following section will discuss some of the mechanisms you can use to control the type of builds that are produced.

### Project Resolutions

All the deployment methods will always try to determine the project type based on the following project resolution ordering:

* docker-compose.yml
* Dockerfile.\<device-type>
* Dockerfile.\<arch>
* Dockerfile.template
* Dockerfile
* package.json

This resolution mechanism looks at the files in the root of the directory you are deploying. If it finds a `docker-compose.yml` file, it will ignore all the other types and build a multicontainer release based on the service specification in the `docker-compose.yml` file.

If `docker-compose.yml` is not specified, the resolution system will assume a single container deployment and will build based on a `Dockerfile.*` file. These Dockerfiles can have extensions of `.<device-type>`, `.<arch>` or `.template`, and the build system will use the most appropriate file based on the targeted device or fleet. This is best described with an example:

In our example at the root of our project repo we have the following `Dockerfile.*` files:

```shell
project: $ tree -a
.
├── Dockerfile.raspberrypi3
├── Dockerfile.i386
└── Dockerfile
```

When we push this project to a fleet that has its default device type set to `Raspberry Pi 3`, the build system will use the device type specific `Dockerfile.raspberrypi3` file to build from. If we instead pushed this to an `Intel NUC` fleet, the build would use the `Dockerfile.amd64` file. When pushing to any other device type, the regular `Dockerfile` would be used to perform the build. This type of project selection will also work in service folders of multicontainer deployments; you can see an example of that in our [Getting started with multicontainer project](https://github.com/balenalabs/multicontainer-getting-started/tree/master/haproxy).

The file extensions are equivalent to `BALENA_MACHINE_NAME` for `.<device-type>` and `BALENA_ARCH` for `.<arch>` from the template files discussed in the next section. To find the correct name have a look at our [machine names and architectures list](/reference/hardware/devices).

### Template Files

Often it's desirable to create a single Dockerfile that can be used and built for multiple different device types and CPU architectures. In this case, a `Dockerfile.template` file can be used. This [dockerfile template](/learn/develop/dockerfile#dockerfile-templates) will replace the template variables before the build is started. Currently the builder supports the following build variables:

| Variable Name         | Description                                                                                                                                                                                                                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BALENA\_APP\_NAME     | The name of the fleet.                                                                                                                                                                                                                                                          |
| BALENA\_ARCH          | The instruction set architecture for the base images associated with this device.                                                                                                                                                                                               |
| BALENA\_MACHINE\_NAME | The name of the yocto machine this board is base on. It is the name that you will see in most of the balena [Docker base images](/reference/base-images/balena-base-images). This name helps us identify a specific [BSP](https://en.wikipedia.org/wiki/Board_support_package). |
| BALENA\_RELEASE\_HASH | The hash corresponding to the release.                                                                                                                                                                                                                                          |
| BALENA\_SERVICE\_NAME | The name of the service defined in the `docker-compose.yml` file.                                                                                                                                                                                                               |

You can find the values of `%%BALENA_ARCH%%` and `%%BALENA_MACHINE_NAME%%` for a specific device type [here](/reference/hardware/devices).

## Private Base Images

In many cases, you will want to deploy container images from a private Docker Hub account or a personally hosted registry. In order to do this, you need to enable `balena` to authenticate with the private registry during the build, which is done by passing the `--registry-secrets` option with a path to the authentication secrets. An example is shown below:

For `balena push`:

```shell
$ balena push myFleet --registry-secrets ../registry-secrets.yml
```

Or for `balena deploy`:

```shell
$ balena deploy myFleet --registry-secrets ../registry-secrets.yml
```

and the `registry-secrets.yml` file is outside of the code repository and has the following format:

```yaml
'': # Use the empty string to refer to the Docker Hub
  username: balena
  password: secretpassword
'my-registry-server.com:25000':
  username: myregistryuser
  password: secretpassword
'eu.gcr.io': # Google Container Registry
  username: '_json_key'
  password: '{escaped contents of the GCR keyfile.json file}'
'ghcr.io': # GitHub Container Registry
  username: GITHUB_USERNAME
  password: PERSONAL_ACCESS_TOKEN
```

It should be noted that in this case, the devices will still pull the container images from the balenaCloud registry. The authentication just allows the build step access to pull your private image at build time.

## Build Time Secrets and Variables

Often it is necessary to use passwords or secrets during your build to fetch proprietary files or code but not have these sensitive files be downloaded to all the devices. For this reason `balena push` and `balena deploy` allow defining a `.balena` folder to hold secret files and variables that will get exposed to the image build but not propagate down to devices.

#### Build Time only Secret File

To use build secrets, make a subdirectory `.balena` in the root of your repository. Inside that directory, make another directory named `secrets` and a file named `balena.yml`. Without any secrets, your tree should look like:

```shell
.
├── docker-compose.yml
├── .balena
│   ├── balena.yml
│   └── secrets
├── service1
│   └── Dockerfile.template
└── service2
    └── Dockerfile.template
```

To add a secret file, first add the file to the `.balena/secrets` directory:

```shell
.
├── docker-compose.yml
├── .balena
│   ├── balena.yml
│   └── secrets
│       └── super-secret-recipe
├── service1
│   └── Dockerfile.template
└── service2
    └── Dockerfile.template
```

Now, in the `.balena/balena.yml` file, add the following:

```yaml
build-secrets:
  global:
    - source: super-secret-recipe
      dest: my-recipe
```

This will mount the `super-secret-recipe` file into `/run/secrets/my-recipe` file in every build container. However, the `/run/secrets` folder will not be added to the build context that is sent to the Docker daemon (or balenaEngine), and therefore:

* The `/run/secrets/` folder will not be present in the image that is deployed to the devices.
* The `COPY` or `ADD` Dockerfile directives will **not** be able to copy files from that folder.
* The folder will be available "for the duration of `RUN` directives", such that secrets can be accessed by scripts/code at image build time, for example:

```dockerfile
RUN cat /run/secrets/my-recipe | secret_processing_script.sh
```

To add a secret file to a specific service's build:

```shell
.
├── docker-compose.yml
├── .balena
│   ├── balena.yml
│   └── secrets
│       ├── super-secret-recipe
│       └── super-secret-recipe-2
├── service1
│   └── Dockerfile.template
└── service2
    └── Dockerfile.template

4 directories, 6 files
```

and balena.yml:

```yaml
build-secrets:
    global:
        - source: super-secret-recipe
          dest: my-recipe
    services:
        service1:
            - source: super-secret-recipe-2
               dest: my-recipe2
```

This will mount the `super-secret-recipe` file as `/run/secrets/my-recipe` for all services, and `super-secret-recipe-2` as `/run/secrets/my-recipe2` for `service1` only. Again, note that the `/run/secrets` folder is only available during the image build, and not present in the image that is deployed to the devices.

Subdirectories are supported in both the source (`.balena/secrets`) and the destination (`/run/secrets`).

{% hint style="warning" %}
Currently `balena build` and `balena deploy` do not support build time secret files out of the box and need to be pointed to a [balenaEngine](https://www.balena.io/engine) instance. Refer to the [`balena build`](/reference/balena-cli/latest#build) and [`balena deploy`](/reference/balena-cli/latest#deploy) command references for additional documentation.
{% endhint %}

#### Build variables

It is also possible to define build variables that will be added to your build from the balena.yml file:

```yaml
build-variables:
  global:
    - MY_VAR_1=This is a variable
    - MY_VAR_2=Also a variable
  services:
    service1:
      - SERVICE1_VAR=This is a service specific variable
```

These variables can then be accessed in your Dockerfile through the ARG instruction. For example:

```dockerfile
FROM balenalib/armv7hf-debian

ARG MY_VAR_1

RUN echo "The build variable is ${MY_VAR_1}"
```

Build variables should **NOT** be used to hold secrets like access tokens or passwords if the Docker image is accessible to untrusted parties, because the Dockerfile ARG instruction may be stored in the image as the [Docker documentation advises](https://docs.docker.com/engine/reference/builder/#arg):

{% hint style="danger" %}
It is not recommended to use build-time variables for passing secrets like github keys, user credentials etc. Build-time variable values are visible to any user of the image with the docker history command.
{% endhint %}

However, secrets like tokens and passwords can be used in instructions like RUN through the mounted secret files, for example:

```dockerfile
RUN /bin/cat /run/secrets/my-recipe | command_that_reads_secrets_from_stdin
```

Files under the .balena folders are not saved in the final image, hence being more secure than ARG.

If you are interested in seeing an example of build time secrets and variables see this [project](https://github.com/balena-io-examples/example-build-secrets-and-variables). Note this is just a toy project and in a real world setting it is not advisable to commit your `.balena` secrets folder into the git repository. You should always add it to your `.gitignore` file.

## The balenaCloud build server

The build server is a powerful tool that compiles code specifically for your device's architecture. With our build servers, compiling a complex dependency tree can be done in seconds, as compared to the minutes or even hours it may take to build on your device.

All code that is pushed using `balena push <MY_FLEET>` or `git push` to your balenaCloud devices is sent to a build server, and then, after the release is built, it is deployed to your devices.

The build server consists of a central build server and a number of Docker daemons on build workers. When a build is triggered, the builder first determines the CPU architecture of the fleet's default device type, and based on that determines what build worker will be used for the build. For [ARM](https://en.wikipedia.org/wiki/ARM_architecture) device types, there are build workers with `armv6l`, `armv7l`, and `armv8l` architectures. For [amd64](https://en.wikipedia.org/wiki/X86-64) based devices, native `x86_64` build workers are used. Finally the `armv5e` and `i386` architecture device types are always built using emulation.

In the case where the `--emulated` flag is used, the build is built on an `x86_64` machine with qemu emulation to match the CPU architecture of the fleet's default device type.

If you push a project with only a `Dockerfile`, `Dockerfile.template`, or `package.json` file, a single container image will be built and deployed to your device. The single container will show up on the device dashboard as a service with the name `main`.

For [multicontainer](/learn/develop/multicontainer) fleets (Microservices [fleet types](/learn/accounts/fleet-types)), a `docker-compose.yml` file at the root of the project directory will start multiple simultaneous image builds, each with their own [build logs](#release-logs).

## View Past Deployments

All successful deployments will result in a release being added to balenaCloud. These releases are tracked in their own dashboard page accessed via the fleet:

<figure><img src="/files/Z51MMwhBFgfAAmyfLA08" alt=""><figcaption></figcaption></figure>

The releases page includes a list of all attempted and deployed releases, with information on the status of the release, when it was completed, how long it took, and how many devices are on that particular release. Clicking any row will open up a summary page specifically for that release, with windows showing the `docker-compose.yml` file and Build Logs:

<figure><img src="/files/uMYIMQ81oFH3v9N5LZE5" alt=""><figcaption></figcaption></figure>

Much like with the device list, [filters](/learn/manage/filters-tags#device-filters) can be added to the release list by clicking *Add filter* and filling in the appropriate fields:

<figure><img src="/files/ls1R5uZDbXUbFWyDJ6ZI" alt=""><figcaption></figcaption></figure>

[Saved views](/learn/manage/filters-tags#create-a-view) can also be created to return to a specific collection of filters.


# Release strategy


# Release policy

When managing a fleet, you may require devices to be running different releases. By default, fleets follow a rolling release policy where new releases are deployed to all devices in the fleet once successfully built. However, you can customize this behavior, so the fleet or individual devices remain on a fixed release, by utilizing release pinning.

You may define the fleet and device release policies via the [balenaCloud dashboard](https://dashboard.balena-cloud.com/). We also offer the ability to do so programmatically via the:

{% tabs %}
{% tab title="API" %}

* [Pin a Fleet/Block/App to a release](/reference/api/resources/fleet#pin-entire-fleet-to-a-specific-release-by-id)
* [Make a Fleet/Block/App track the latest release](/reference/api/resources/fleet#enable-automatic-update-tracking-for-a-fleet)
* [Pin a Device to a release](/reference/api/resources/device#pin-device-to-a-specific-release-by-id)
  {% endtab %}

{% tab title="Node SDK" %}

* [Pin a Fleet/Block/App to a release](/reference/sdk/node-sdk/latest/models/application#pintorelease)
* [Make a Fleet/Block/App track the latest release](/reference/sdk/node-sdk/latest/models/application#tracklatestrelease)
* [Pin a Device to a release](/reference/sdk/node-sdk/latest/models/device#pintorelease)
* [Make a Device track the fleet's release policy](/reference/sdk/node-sdk/latest/models/device#trackapplicationrelease)
  {% endtab %}

{% tab title="Python SDK" %}

* [Pin a Fleet/Block/App to a release](/reference/sdk/python-sdk/latest#pin_to_release)
* [Make a Fleet/Block/App track the latest release](/reference/sdk/python-sdk/latest#track_latest_release)
* [Pin a Device to a release](/reference/sdk/python-sdk/latest#pin_to_release-1)
* [Make a Device track the fleet's release policy](/reference/sdk/python-sdk/latest#track_application_release)
  {% endtab %}

{% tab title="CLI" %}

* [Pin a Fleet/Block/App to a release](/reference/balena-cli/latest#fleet-pin)
* [Make a Fleet/Block/App track the latest release](/reference/balena-cli/latest#fleet-track-latest)
* [Pin a Device to a release](/reference/balena-cli/latest#device-pin)
* [Make a Device track the fleet's release policy](/reference/balena-cli/latest#device-track-fleet)
  {% endtab %}
  {% endtabs %}

## Pin fleet to a release

By default, the setting is set to `track latest`, which means that new releases are immediately deployed to all devices in the fleet when built. When the fleet is pinned, all devices that are not currently pinned to a release are updated to run the pinned release, and in the future, releases will not be deployed until the pinned release is updated to a different release or set to `track latest`.

You can set the release the fleet is pinned to via the Releases card on the on the Fleet Summary page.

<figure><img src="/files/kvx3UnnhRWA2IlkLHb5H" alt=""><figcaption></figcaption></figure>

This can also be achieved using the `Pin to release` setting on the Fleet settings page.

<figure><img src="/files/iIijLdZFOH3Y7p9bmfqY" alt=""><figcaption></figcaption></figure>

The dropdown menu at each of the above locations displays all successful and valid releases for the fleet.

You can also pin a fleet to a release via the CLI as follows:

* Pin to a specific release: `balena fleet pin <FLEET_SLUG> <RELEASE_COMMIT>`
* Track latest: `balena fleet track-latest <FLEET_SLUG>`

## Pin device to a release

By default, all devices track the fleet release. However, you may wish to run a different release on select devices, for example, a development device or when performing a [canary deployment](/learn/introduction/production-plan#canary-deployments).

There are several ways to achieve this from the Device dashboard. The dropdown options are identical to the ones when trying to pin the fleet to a release:

* On the Devices page, you can select one or more devices using the checkboxes present on the table. Next, open the `Modify` menu and select the `Pin to release` option.

<figure><img src="/files/7zzq43C5jPTQOV9ODcyZ" alt=""><figcaption></figcaption></figure>

* Alternatively, on hovering over the `Target release` property in the Device summary page, you will see a pencil icon appear. This can be used to pin the release as well.

<figure><img src="/files/ra0aLKDbsfyDBxheanDQ" alt=""><figcaption></figcaption></figure>

* Lastly, the Settings page of a device also has the option to pin the release.

<figure><img src="/files/anpEoqDH8LtdHxzXDW6v" alt=""><figcaption></figcaption></figure>

Once the device has been pinned to a release and updated, its `Target release` column updates to the pinned release. It will show a pin, rather than just showing the release targetted by the fleet. The `Release policy` column also updates to say `Pinned`.

<figure><img src="/files/5uq4PYPjn4xyG9BqlvSl" alt=""><figcaption></figcaption></figure>

You can also pin a device to a release via the CLI as follows:

* Pin to a specific release: `balena device pin <DEVICE_UUID> <RELEASE_COMMIT>`
* Track latest: `balena device track-fleet <DEVICE_UUID>`

{% hint style="info" %}
For more details about using the API to manage the release policy see the [Fleet Management Masterclass](/learn/more/masterclasses/fleet-management).
{% endhint %}


# Update locks

There are **two independent locking mechanisms** on balenaOS devices, both using the same lock file path (`/tmp/balena/updates.lock`):

| Mechanism    | What it prevents                                                                                      | How it works                                                                             | Checked by      |
| ------------ | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------- |
| **lockfile** | **Application updates** and **config-change reboots**. Supervisor will not kill/restart your services | Lock is "held" when the file **exists** (created with `O_EXCL` or the `lockfile` binary) | Supervisor      |
| **flock**    | **Host OS update reboots** (e.g. `safe_reboot`, `hostapp-update`)                                     | Lock is held when a process holds an exclusive `flock()` on the file                     | Host OS scripts |

During critical operations, both mechanisms can be used together for full protection against app updates, config-change reboots, **and** host OS update reboots.

For details on the flock mechanism (host OS update reboots), see the [OS update locks documentation in meta-balena](https://github.com/balena-os/meta-balena/blob/master/README.md#os-update-locks).

## Lockfile (application updates)

Locking updates means that the balena Supervisor will not be able to kill the services running on the device for an update. This is meant to be used at critical sections of your code where you don't want the process to be interrupted, or to ensure that updates are installed only at certain times. Moreover, any configuration changes that will reboot the device won't trigger reboots if locks are applied. Config changes not requiring a reboot will be applied as usual.

In order to do this, users can create a lockfile in a way that it has exclusive access, which will prevent the device Supervisor from killing and restarting the app. As with any other lockfile, the Supervisor itself will create such a file before killing the app, so you should only create it in exclusive mode. This means that the lockfile should only be created if it doesn't already exist. The exclusive access is achieved by opening the lockfile with the [O\_EXCL and O\_CREAT flags](https://linux.die.net/man/3/open), and several tools exist to simplify this process with examples given [below](#creating-the-lockfile).

For multicontainer releases, a release will only be updated if all of the services can be updated. While locks are per-service, having the update lock in a single service will prevent all services from updating to a new release.

The presence of a lockfile will ensure that your services do not get killed, but updates will still be downloaded by the Supervisor, ready to be applied once the lockfile no longer exists.

On devices running Supervisor v13.1.0 or newer, the Supervisor creates lockfiles as the `nobody` user, with UID 65534.

### Location of the lockfile

**Note:** Trying to remove `/tmp/balena` or legacy `/tmp/resin` directories will result in a `resource busy` error.

On devices running Supervisor v7.22.0 and higher, the lockfile is located at `/tmp/balena/updates.lock`. This lock is cleared automatically when the device reboots, so the user app must take it every time it starts up.

On older devices (with v4.0.0 <= Supervisor version < v7.22.0), the lock is located at `/tmp/resin/resin-updates.lock`. The latest Supervisor versions still take the lock at this legacy path for backwards compatibility.

Legacy Supervisors (< v4.0.0) have the lock at `/data/resin-updates.lock`. This lock is only supported on devices running balenaOS 1.X. This old lock has the problem that the Supervisor has to clear whenever it starts up to avoid deadlocks. If the user app has taken the lock before the Supervisor starts up, the lock will be cleared and the app can operate under the false assumption that updates are locked (see [issue #20](https://github.com/balena-os/balena-Supervisor/issues/20)). We therefore strongly recommend switching to the new lock location as soon as possible.

### Creating the lockfile

There are many different tools and libraries to provide proper lockfile functionality and a few common examples are shown below.

**Note:** Just creating the lockfile, for example by using `touch /tmp/balena/updates.lock`, is not adequate to prevent updates. A file created in this way won't have the exclusive access flag set, and thus does not provide reliable locking. Additionally, a file needs to be held by a process to be counted by the system as a lockfile.

#### Shell

One simple way to create a lockfile is using [lockfile](https://linux.die.net/man/1/lockfile) (available for example in Debian from the `procmail` package):

```shell
lockfile /tmp/balena/updates.lock
# ... (do things)
rm -f /tmp/balena/updates.lock
```

For more examples and explanation of the functionality, check the links to the specific tools above.

#### Javascript

Using the [`lockfile` library](https://www.npmjs.com/package/lockfile), the lock can be acquired like in this example:

```javascript
import lockFile from 'lockfile';

lockFile.lock('/tmp/balena/updates.lock', function(err) {
    // A non-null err probably means the Supervisor is about to kill us
    if (err != null) { throw new Error('Could not acquire lock: ', err); }

    // Here we have the lock, so we can do critical stuff:
    doTheHarlemShake();

    // Now we release the lock, and we can be killed again
    return lockFile.unlock('/tmp/balena/updates.lock', function(err) {
        // If err is not null here, something went really wrong
        if (err != null) { throw err; }
    });
});
```

#### Python

In Python you can use the [`lockfile` library](http://pythonhosted.org/lockfile/lockfile.html#examples)

```python
from lockfile import LockFile
lock = LockFile("/tmp/balena/updates")
with lock:
    print lock.path, 'is locked.'
```

Check the link for more examples and other Python libraries that provide locking.

### Overriding the lock

The update lock can be overridden in case you need to force an update, for instance, if your app has hung in a critical section.

The recommended way to do this is to use the 'Override the update lock ...' toggle in the [Fleet or Device Configuration](https://github.com/balena-io/docs/blob/main/pages/learn/manage/configuration/README.md#managing-device-configuration-variables) page. Go to the configuration page of the device or fleet, locate the 'Override the update lock ...' item from the list, click the activate button, and set the toggle to enabled. After disabling the toggle, update locks may be set again and will be respected.

Also, you can programatically override locks one time by querying the `/v1/update` endpoint of the [Supervisor HTTP API](https://github.com/balena-io/docs/blob/main/pages/reference/supervisor/supervisor-api/README.md), with `{ "force": true }` as body. Note that this will not set the lock override config var.

Please note that setting the override is a one-time action. Locks set previously are deleted upon setting the config var, and will need to be recreated.


# Controlling the update strategy

It is possible to control the order and way in which the steps to perform an update are executed by the balena device supervisor by defining a specific *update strategy*. The strategy allow users to choose between four modes that are suited for different applications, depending on available resources and the possible need to have a container running at all times.

Update strategies can be applied by setting a [docker-compose label](/reference/supervisor/docker-compose#labels). The two labels that are involved are:

* `io.balena.update.strategy`, and
* `io.balena.update.handover-timeout`.

Setting the `io.balena.update.strategy` label to a valid value selects the update strategy. The possible values are:

* [`download-then-kill`](#download-then-kill) (default)
* [`kill-then-download`](#kill-then-download)
* [`delete-then-download`](#delete-then-download)
* [`hand-over`](#hand-over)

which are explained below. The `io.balena.update.handover-timeout` label is only used in the `hand-over` strategy, and its use is explained in the [strategy's description](#hand-over).

All update strategies below honor the [device update locks](/learn/deploy/release-strategy/update-locking) which you can use prevent updates temporarily.

## download-then-kill

This is the default strategy, and it is selected if the variable is not set or if it has an invalid value. Its behavior corresponds to the way balena traditionally works:

* When an update is available, the Supervisor downloads the new service image.
* Once the download is complete, the Supervisor kills the container for the old service version.
* Immediately afterwards, the Supervisor creates and starts the container for the new service version, and then deletes the old image.

This strategy is suited for the general case of container update, where resources are not particularly constrained (as pulling the new image while the old container runs takes up some extra RAM), and when a zero-downtime update is not necessary but we still want to keep downtime to a minimum.

Is important to notice that the while the strategy is set per service, the supervisor waits until all images for the target release have been downloaded before killing any running services.&#x20;

## kill-then-download

This strategy is meant for resource-constrained scenarios or when the images be pulled are particularly large, so we need to keep RAM usage to the minimum, albeit at the cost of some extra downtime. It works as follows:

* When an update is available, the Supervisor kills the container for the old service version.
* After this, the Supervisor downloads the image for the new service version.
* Once the download is complete, the Supervisor creates and starts the new container, and deletes the old image from disk.

## delete-then-download

This strategy is meant for resource-constrained scenarios or when the images be pulled are particularly large, so we need to keep disk usage to the minimum, albeit at the **cost of extra downtime and higher bandwidth usage.** It works as follows:

* When an update is available, the Supervisor kills the container for the old version, and then deletes the corresponding image.
* After this, the Supervisor downloads the image for the new version.
* Once the download is complete, the Supervisor creates and starts the new container.

{% hint style="warning" %}
This strategy is only recommended for extreme low storage scenarios, where the available storage cannot even fit the target [image deltas](/learn/deploy/delta). For most cases, using the default strategy or the `kill-then-download` strategy (if memory usage is a concern), and ensuring [deltas are enabled](/learn/deploy/delta) is the recommended approach.
{% endhint %}

## hand-over

This strategy is suited for scenarios where there are enough resources and it is critical that the downtime is *zero*, that is, that the app runs continually even during an update. For this strategy to work properly, the user has to consider the way the update works and include code to perform a handover between the old and new releases. Its behavior is as follows:

* When an update is available, the Supervisor downloads the new image.
* When the download is complete, the Supervisor creates and starts the new container, *without killing the old one*.
* The old and new releases should communicate between each other so that the old one frees any resources that the new one needs (e.g. device files, database locks, etc) and the new version can start running fully.
* Once this "handover" is performed between the releases (old or new), your service must signal to the Supervisor that the old version is ready to be killed, by creating a file at the path configured under the environment variable  `BALENA_SERVICE_HANDOVER_COMPLETE_PATH`.
* When the Supervisor detects that the file has been created, the Supervisor kills the old container and deletes it from disk.
* If the file is not created after a time defined by the `io.balena.update.handover-timeout` label, the Supervisor kills the old version.

The `io.balena.update.handover-timeout` label defines this timeout in milliseconds, and defaults to 60000 (i.e. 1 minute). The communication between the old and new versions has to be implemented by the user in whatever way they see fit, for example by having the old version listen on a socket or port and having an endpoint for the new version to announce it's ready to take over. It is important to note that both versions will share the folder at `BALENA_SERVICE_HANDOVER_COMPLETE_PATH` and the network namespace, so they can use any of those to communicate. &#x20;

It's also important to note that because the handover requires both the current and target service containers to run at the same time, they cannot configure conflicting resources, for instance, if the old container exposes a port on the host network, the new container will fail to start with a `port is already allocated` error.


# Delta updates

When a new release is successfully created, your devices are notified, and will initiate an update of their running containers. The regular device update uses the Docker pull mechanism. It requests all the [layers](https://docs.docker.com/engine/storage/drivers/#images-and-layers) of the new container image that are not present on the device (i.e. not shared with the previous image). Then from these layers the new image is assembled on the device, and replaces the previous version of the fleet services. This process potentially moves a lot of data, uses a lot of space on the device to hold both the old and the new images, and the device can be in a sensitive state while Docker is updating (e.g. in case there's an unexpected power outage during that time).

To address some of these issues, we have implemented a "binary delta" update process. Instead of initiating a Docker pull when the device is notified about an update, it requests the balena servers to provide just the differences between the old and new container image. This comparison is done on the full image level, comparing the actual content, regardless of the layers used, resulting in the minimum amount of change required to get from the previous release to the new one. In the worst case (i.e. completely replaced image) the binary delta is equal size to the Docker pull (the device needs to download the full image). In most cases, the binary delta will be much smaller.

Once the delta (difference between the old and new image) is calculated, the device downloads and applies this delta onto the old image, in place. When the process is finished, the new container image (new release) is started.

These binary deltas save on the amount of data needed to be downloaded, reduce the storage space requirements on the device to perform an update, and shorten the time taken for the update to apply.

## Enabling delta updates

The delta updates feature is now available in all devices running balenaOS >= 2.47.1. For devices running balenaOS < 2.47.1, updating to >= 2.47.1 via a [self-service update](/reference/os/updates/self-service) will enable delta updates for your device.

## Delta behavior

Before devices can update using deltas, a delta must be generated between the release a device is currently running and the one it is updating to. There are two ways deltas are generated:

1. Automatically between the last successful and the new release during a build on the balenaCloud builder - these are known as "build-time" deltas.
2. Automatically when a device is requesting to update from or to a release for which no delta has been generated before - these are known as "on-demand" deltas and can typically happen if the device was not on the latest release when the new release was pushed, or the user did not use the balenaCloud builder for the new release.

On-demand deltas may take a while to generate, depending primarily on the size of the images involved. While the delta is generating, the device keeps polling the API, checking if the delta is ready. If a delta already exists, this step is skipped.

The *Download progress* bar on the dashboard might show for only a short time, much shorter than in a normal update. In the most common development patterns, there are usually very small changes between one version of the image and the next (e.g. fixing typos, adding a new source file, or installing an extra OS package), so when using deltas these changes are downloaded much quicker than before.

Devices using delta updates still follow the prescribed [update strategy](/learn/deploy/release-strategy/update-strategies).


# Offline Updates

Offline updates is a process to update devices without needing an internet connection. It involves preloading an image and reflashing it to on a device in a way that it retains its unique balena identity, releases, and configurations. This process helps in scenarios where a device's internet access is unavailable, limited, blocked, or even when it's air-gapped.

## Overview of the process

When a device is reflashed, it defaults back to a factory state. The device is provisioned with a new identity, a new API key, and updated [`config.json`](/reference/os/configuration#valid-fields) settings. All services, data and logs stored on the device are erased permanently.

With the offline updates process, the device still resets to a default factory state. It adds a new API key while preserving its identity in [`config.json`](/reference/os/configuration#valid-fields). It uses [`balena preload`](/reference/balena-cli/latest#preload) to load an updated release. That way, the device will pick up right where it left off with the same name and UUID but with an updated release or/and balenaOS update.

Broad steps of the process include:

1. Downloading appropriate balenaOS version (can be an upgrade or the same version).
2. Generating a device-specific `config.json` file for the device.
3. Inserting the custom `config.json` file into the downloaded balenaOS image.
4. Running `balena preload` on the image, pointing to whichever version of your code you want to deploy to the device.
5. Flashing this preloaded image to an SD card, a device's eMMC or a separate (flasher) USB drive.
6. Updating device state on balenaCloud and optionally tagging the device.

When you insert the SD card or USB drive into your device and boot it, the device will be reflashed, retaining its balena identity, and all your updates will be in place and running.

## Configuration and Data Recovery

Some consideration is required if an application requiring persistent data storage is being used to recover user data while using the offline update process. The application can't use the pre-provisioned [named volumes](/learn/develop/multicontainer#named-volumes), since these will be wiped during the offline update process.

If this is the case, mount an external mass storage (USB) device into a privileged data container and share it with other containers (if applicable) via NFS or a similar network storage protocol for the data. These external storage devices are not a part of the update process. Hence, data on them would be left intact, as long as they are temporarily disconnected during the update process.

By contrast, a typical balena online update leaves services and data intact, and [persistent logging](/reference/os/configuration#persistentlogging) can be enabled to save your logs across device restarts.

## Performing an Offline Update

To perform an offline update, we will be using [balena-cli](/reference/balena-cli/latest). All commands should work on Linux distributions running Docker on Linux Kernel with AUFS and overlay filesystem support. For Windows and macOS, the last version of Docker Desktop supporting AUFS is 18.06.1

{% hint style="warning" %}
In an offline updates process, all data on the device is wiped at this point, making this different from a typical software update process in the balena ecosystem. Any additional user data and system settings written to various device partitions would be lost in this process.
{% endhint %}

Offline update includes the following steps:

* [Setup](#setup)
* [Create/use pre-existing fleet](#create-use-pre-existing-fleet)
* [Create/use pre-existing offline device](#create-use-pre-existing-offline-device)
* [Download balenaOS image](#download-balenaos-image)
* [Configure balenaOS image](#configure-balenaos-image)
* [Create and preload release](#create-and-preload-release)
* [Create update media](#create-update-media)
* [Process of reprovisioning](#process-of-reprovisioning)
* [Update device registration(s)](#update-device-registration-s)

The process needs some prerequisite knowledge of the balena ecosystem, [balena-cli](/reference/balena-cli/latest) commands and shell commands. Please read all instructions carefully and make sure to try the update process first on a test device.

### Setup

> Download and install [balena-cli](/reference/balena-cli/latest) on a Linux distribution. The commands have been tested to work on Ubuntu 20.04.

Several `balena-cli` commands require access to a balenaCloud account. Those commands require creating a CLI login session by running [`balena login`](/reference/balena-cli/latest#login) in the terminal.

```bash
$ balena login
```

Store the filename of your OpenSSH private key in an environment variable or generate an SSH key using the commands below. The SSH keys will be added to the device and used to SSH into the device after provisioning to help in debugging if needed.

```bash
# (optional) if you already have SSH key(s)
$ ssh-keygen -o -a 100 -t ed25519 -f id_ed25519 -C 'offline-updates' -N ''

# must contain the filename of the OpenSSH private key
$ ssh_key=id_ed25519.pub
```

### Create/Use Pre-existing Fleet

Initialize the `arch` and `device-type` environment variable with correct CPU architecture (`aarch64`, `armv7l`, etc.) and device type (`raspberrypi4-64`, `raspberrypi3`, etc.). The list of names for supported device types and their architectures can be found on the [hardware](/reference/hardware/devices) page.

If a pre-existing fleet needs to be re-used, then initialize the `fleet_name` variable with that fleet's's name.

```bash
$ arch=<CPU ARCHITECTURE TYPE>
$ device_type=<DEVICE_TYPE>
$ fleet_name=offline-${arch}
```

These environment variables will be used later in the process. If a pre-existing fleet needs to be used, then the next step can be skipped. Otherwise, create a new balenaCloud fleet by running [`balena fleet create`](/reference/balena-cli/latest#fleet-create).

```bash
$ balena fleet create ${fleet_name} --type ${device_type}
```

Initialize the `fleet_slug` environment variable with the command below to store the slug of the fleet.

```bash
$ fleet_slug=$(balena fleet ${fleet_name} | grep Slug | awk '{print $3}')
```

### Create/Use Pre-existing Offline Device

If a new offline device is being created, then the following command can be used. Otherwise, the `uuid` environment variable can be initialized with the UUID of a pre-existing device that needs to be updated.

```bash
$ uuid=$(uuidgen | tr '[:upper:]' '[:lower:]' | sed 's/-//g')
```

OR

```
$ uuid=<UUID OF YOUR DEVICE>
```

With [`balena device register`](/reference/balena-cli/latest#device-register), devices can be preregistered to a balenaCloud fleet involving a simple call with a unique identifier for the device. You can read more about the full process of pre-registering a device in the [balena-cli advanced masterclass](https://docs.balena.io/learn/deploy/pages/tCSZw6iQBfvGBg9ENzax#id-5.2-preregistering-a-device). This step can be skipped if a pre-existing device is needed to be updated.

```bash
$ balena device register ${fleet_slug} --uuid ${uuid}
```

### Download balenaOS Image

Download the latest production version of [balenaOS](https://www.balena.io/os) for the device type initialized in the `device_type` version.

```bash
$ os_version=$(balena os versions ${device_type} | head -n 1 | awk '{print $1}')
$ tmpimg=$(mktemp).img

$ balena os download ${device_type} \
  --output ${tmpimg} \
  --version ${os_version}
```

### Configure balenaOS Image

Configure the downloaded image by injecting a [config.json](/reference/os/configuration#valid-fields) file using the [`balena os configure`](/reference/balena-cli/latest#os-configure) command. Most common system settings can be (re)specified via [config.json](/reference/os/configuration#valid-fields). To preserve the pre-existing registered device's identity, the same `uuid` initialized earlier will be used to generate a config.json file.

```bash
$ tmpconfig=$(mktemp)
$ config=$(mktemp)

$ balena config generate \
    --device ${uuid} \
    --version ${os_version} \
    --network ethernet \
    --appUpdatePollInterval 10 \
    --output ${tmpconfig} \
    && cat ${tmpconfig} | jq .

$ cat < ${tmpconfig} \
    | jq --arg keys "$(cat ${ssh_key})" '. + {os: {sshKeys: [$keys]}}' > "${config}" \
    && cat < ${config} | jq .

$ balena os configure ${tmpimg} \
    --config ${config}

$ rm ${tmpconfig}
$ rm ${config}
```

### Create and Preload Release

Offline updates revolve around the concept of [balena preload](/reference/balena-cli/latest#preload). Preload is used to flash the balenaOS image and your fleet release in a single step, so the device starts running your release's containers as soon as it boots. Preloading removes the need for your devices to download the initial images directly from balena's build servers, making it an ideal base for the offline update process. Read more about [preloading a device image](https://docs.balena.io/learn/deploy/pages/tCSZw6iQBfvGBg9ENzax#id-5.1-preloading-a-device-image).

{% hint style="info" %}
[balena preload](/reference/balena-cli/latest#preload) functionality is not available with a secure boot OS image. Read more about [why application preloading is not supported in this case](/reference/os/secure-boot-and-full-disk-encryption/overview#application-preloading-not-supported).
{% endhint %}

Preload involves flashing a fleet's release with the balenaOS image. If the pre-existing fleet doesn't have any releases, then a release needs to be created using [`balena deploy`](/learn/deploy/deployment#balena-build-and-deploy). Navigate to the directory of your source code folder and run the command below to deploy the latest release of your fleet. If a release is present already, then the next step can be skipped.

```bash
$ balena deploy ${fleet_slug} --build --emulated --source .
```

The following steps will flash the latest release onto the balenaOS image downloaded in the previous steps and pin the device to mentioned release commit.

```bash
$ commit=$(balena fleet ${fleet_slug} | grep Commit | awk '{print $3}')

$ balena preload ${tmpimg} \
    --fleet ${fleet_slug} \
    --commit ${commit} \
    --pin-device-to-release
```

### Create Update Media

Next, a USB flash drive, an SD card or any relevant storage media needs to be prepared and flashed. This storage media will be used to update the device through the offline process. Plug in your storage media and run the following commands.

{% hint style="danger" %}
The process of flashing will delete all data stored on the storage media.
{% endhint %}

```bash
# list the devices available to flash
$ balena util available-drives

# Please make sure `--drive` is really the disk you want to write to.
$ sudo balena local flash ${tmpimg} \
    --drive /dev/{{flash-usb-disk}}

$ rm ${tmpimg}
```

### Process of Reprovisioning

{% hint style="danger" %}
For devices with internal storage, this procedure erases the internal media of your device. Remove any mass storage devices containing user data.
{% endhint %}

With the update media already having the latest release of the fleet preloaded, follow the device's provisioning instructions present on balenaCloud dashboard for your specific device.

An example for Raspberry Pi devices: insert the recently flashed SD card and power up the device. When the process is complete, (re)connect any mass storage devices containing user data back to the device. Reconnect the device to the local air-gapped network(s). Later, use SSH to connect and inspect logs, etc.

#### Strategies to remotely update with an SD card or USB device

If a device isn't locally deployed, one can ship the flashed SD cards or USB sticks/drives to a remote location. There someone can run the update by simply inserting them into the devices and booting.

If the target device exists on an air-gapped or Internet restricted network, [inserting ssh keys](/reference/os/configuration#sshkeys) during the configuration step will allow fleet managers at the remote site to connect to the device directly via OpenSSH and verify the update by examining container logs, etc.

If the target device is connected via a low-bandwidth connection, it should eventually establish a connection to balenaCloud. Depending on the connection's quality, it may respond to [web terminal](/learn/manage/ssh-access#using-the-dashboard-web-terminal) commands and output container logs to the dashboard.

### Update Device Registration(s)

This section deals with device registration in the cloud (balenaCloud or openBalena). The following steps help in manually reflecting the new state of the device for offline devices or devices on private networks without Internet access.

#### Patch State Endpoint - Update Device State in the Cloud

This step updates the device state in the cloud (balenaCloud or openBalena) on behalf of the device, as if the device was online. It is only required for devices that do not have an internet connection. If the device has an internet connection, even if low bandwidth, this step may be skipped because the device itself will be able to contact the cloud to update its state.

```bash
$ os_version_tag=$(echo ${os_version} | awk -F'+' '{print $1}')
$ os_version_semver=$(echo ${os_version_tag} | sed 's/v//g')
$ os_revision=$(echo ${os_version} | awk -F'+' '{print $2}' | awk -F'.' '{print $1}')
$ os_variant=$(echo ${os_version} | awk -F'+' '{print $2}' | awk -F'.' '{print $2}')

$ supervisor_version=$(curl --silent https://raw.githubusercontent.com/balena-os/meta-balena/${os_version_tag}/meta-balena-common/recipes-containers/balena-supervisor/balena-supervisor.inc \
    | grep SUPERVISOR_TAG \
    | awk '{print $3}' \
    | sed 's/"//g' \
    | sed 's/v//g')

$ if [ -z "$BALENARC_BALENA_URL" ]; then BALENARC_BALENA_URL=balena-cloud.com; fi

$ release_id=$(curl --silent \
    "https://api.${BALENARC_BALENA_URL}/v6/release?\$filter=startswith(commit,'${commit}')&\$select=id" \
    -H "Authorization: Bearer $(cat ~/.balena/token)" | jq -r .d[].id)

$ curl --silent \
    -X 'PATCH' "https://api.${BALENARC_BALENA_URL}/v6/device(uuid='${uuid}')" \
    -H "Authorization: Bearer $(cat ~/.balena/token)" \
    -H 'Content-type: application/json' \
    --data-binary "{\"os_variant\":\"${os_variant}\",\"os_version\":\"balenaOS ${os_version_semver}+${os_revision}\",\"supervisor_version\":\"${supervisor_version}\",\"is_running__release\":${release_id}}"
```

#### \[Optional] Set Tags on Devices

Tags help identify and track devices in your fleet as to what commit and OS version have they been flashed & updated offline with. One can use [`balena tag set`](/reference/balena-cli/latest#tag-set) to create new tags as needed.

```bash
$ balena tag set 'offline:commit' "${commit}" \
  --device ${uuid}

$ balena tag set 'offline:hostOS' "${os_version}" \
  --device ${uuid}
```

Read more about how the process can work better for your use case in the [offline updates](https://balena.io/blog/offline-updates-make-it-easier-to-update-balena-devices-without-the-internet) blog.


# Optimize your builds

These are just a few tips and tricks to optimize your balena container builds and hopefully reduce the time it takes to build and push. They mostly make use of the caching mechanism in the Docker container builders on our servers. If you want to read more about how Docker caches layers and Docker best practices, head over to [Docker best practices](https://docs.docker.com/articles/dockerfile_best-practices/).

{% hint style="info" %}
For information on using multi-stage builds to reduce image sizes, see the [services masterclass](https://docs.balena.io/learn/deploy/pages/AVNPbJlAuDxvDl7GfgI5#id-6.-multi-stage-builds).
{% endhint %}

## Move `ADD` and `COPY` Commands

Caching in Docker is done by comparing the instructions in the current `Dockerfile` with the ones in the previous build. If the instructions have changed, the cache is invalidated. However, this is slightly different for the `ADD` and `COPY` commands. For these commands, the contents of the files being put into the image are examined. If there are any changes, even in the file metadata, then the cache is invalidated. We recommend you place your `ADD` or `COPY` statements near the end of your Dockerfiles, after all your package installs and source compilation steps have been completed.

## Minimize the number of layers

Reducing the number of layers in your Dockerfile can reduce the build and push time on balena. If we combine two instructions we avoid making another layer so we’re not storing intermediate (and maybe useless) states. Reducing the number of layers can be achieved by chaining multiple commands together with `&&` in `RUN` invocations. e.g. :

```dockerfile
RUN apt-get update && apt-get install -y python
```

However, we recommend you find a balance between readability (and thus long-term maintainability) of the Dockerfile and minimizing the number of layers it uses.

## Avoid installing unnecessary packages

In order to reduce complexity, dependencies, file sizes, and build times, you should avoid installing extra or unnecessary packages just because they might be “nice to have.” For example, you don’t always need to include a text editor.

## Multi-stage builds

Balena supports [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/). When building your application, you might require build-time dependencies, or other files which are not needed at *runtime*. With multi-stage builds, you can use multiple `FROM` statements to describe a new stage. Each stage can use a different base image and you can copy files and artifacts from one stage to another. This allows you to only copy necessary files and tools into the final image you want to ship, keeping it lean. Here is an example illustrating multi-stage build for a `golang` project.

```dockerfile
FROM golang:1.24.3-bookworm AS build # define a build stage

WORKDIR /go/src/github.com/balena-io-projects/app

COPY /app ./

RUN go build

FROM debian:bookworm-20250428-slim # use a different, leaner image in final image

COPY --from=build /go/src/github.com/balena-io-projects/app/ . # copy build artifacts from build stage

CMD ["./app"]
```

Balena base images come in two variants, namely `build` and `run`. Refer to the docs on [the differences between the two variants](/reference/base-images/balena-base-images).

### Using scratch

Most Dockerfiles start from a parent(base) image. Docker has a [reserved image](https://hub.docker.com/_/scratch) `scratch` that has no layers and can be used to create lightweight images. Note that there won't be a root filesystem(rootfs) in the scratch image. This typically means you have to *statically* compile your application if possible or add all dependencies your application needs to run properly.

## Cleaning up after yourself

We can tidy up a bit by cleaning out the apt-cache and cleaning out tmp:

```dockerfile
RUN apt-get update && apt-get install -y \
    curl \
    git \
    libsqlite3-dev \
    && apt-get clean && rm -rf /var/lib/apt/lists/*
```

{% hint style="warning" %}
The above command should never be split over two or more `RUN` commands, as the benefits will be lost.
{% endhint %}

It is also wise to remove any .tar.gz or temporary files in a similar fashion to the above, as this will reduce build size.

## Use .dockerignore

Make use of `.dockerignore` to ignore anything that is in the git repo, but is not strictly needed on the device(s). This can allow you to safely ignore images or assets used to document your project on github or bitbucket.

## Don't do apt-get update or upgrade

This isn't so much of an optimization tip, but more a guideline to ensure maintainable Docker images. Note the below tips were kindly borrowed from [Docker Best Practices](https://docs.docker.com/articles/dockerfile_best-practices/).

* Don’t do `RUN apt-get update` on a single line. This will cause caching issues if the referenced archive gets updated, which will make your subsequent apt-get install fail without comment.
* Avoid `RUN apt-get upgrade` or `dist-upgrade`, since many of the “essential” packages from the base images will fail to upgrade inside an unprivileged container. If a base package is out of date, you should contact its maintainers. If you know there’s a particular package, foo, that needs to be updated, use apt-get install -y foo and it will update automatically.

## Starting long running tasks together

If you have commands that do not depend on each other, they can be started in the background at the same time to decrease build time. An example of this could be two downloads of unrelated sources:

```
RUN wget my-source-1.tar.gz & \
    && wget my-source-2.tar.gz & \
    && wait
```

This will start downloading both files and wait for them to complete. The next layer could then start the build on one or both of them.

## Pro Tips for slimming down your build

These are just a few tips from our engineers on how to reduce your build size:

* npm install commands like `npm install --unsafe-perm -g @some/node-module` can have `&& npm cache clean --force && rm -rf /tmp/*` added in order to clean up the npm cache and the /tmp/npm-... folders it uses.
* apt-get update commands should have a matching `rm -rf /var/lib/apt/lists` in order to clean up the package lists (or `rm -rf /var/lib/apt/*` which is equivalent).
* You can combine the smaller layers together (each RUN/COPY/etc command creates a new layer) in order to reduce the metadata required for each layer and to speed up the updating process (each layer is downloaded individually), eg. you could change:

```dockerfile
RUN mkdir /var/run/sshd
RUN echo 'root:{{ $names.os.short }}' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
```

into

```dockerfile
RUN mkdir /var/run/sshd \
  && echo 'root:{{ $names.os.short }}' | chpasswd
  && sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
```

In order to merge those three layers into just one, without losing any benefits of Docker caching, this would also work well for combing the layers that add the apt mirrors.

* You can potentially add `--no-install-recommends` in your apt-get installs in order to only install the packages you really care about, rather than all the recommended but non-essential packages.

You can exclude `docs/locales` since they're not much use on the device, we do this via the command `COPY 01_nodoc /etc/dpkg/dpkg.cfg.d/` which has the contents:

```
path-exclude /usr/share/doc/*
path-exclude /usr/share/man/*
path-exclude /usr/share/groff/*
path-exclude /usr/share/info/*
path-exclude /usr/share/lintian/*
path-exclude /usr/share/linda/*

path-exclude /usr/share/locale/*
path-include /usr/share/locale/en*
```


# Deploy with balena button

The **Deploy with balena** button allows users to perform a single-click deployment and configuration of a fleet on balenaCloud.

![Deploy with balena](https://balena.io/deploy.svg)

Clicking the **Deploy with balena** button opens the balenaCloud dashboard with a modal window pre-populated with everything required to deploy a fleet. Clicking the *Advanced* toggle in the modal window allows adding additional configuration options. If the project has provided configuration variables via a [configuration file](#balena.yml-configuration-file), then they are pre-populated in this section.

<figure><img src="/files/Bg9acHr8uCZfgWBMyHju" alt=""><figcaption></figcaption></figure>

Clicking *Create and deploy* creates a new fleet and generates a release. Any devices added to the fleet will immediately download and begin running the release.

{% hint style="warning" %}
Currently git submodules are not supported and will not build properly.
{% endhint %}

## Adding a deploy with balena button to a project

You can add the **Deploy with balena** button to any project that can be deployed to balenaCloud. To add the button to a project repository, add the following to, for example, the project repository's README.md file:

`[![balena deploy button](https://www.balena.io/deploy.svg)](https://dashboard.balena-cloud.com/deploy?repoUrl=<your-repo-url>)`

The above example uses a SVG logo as this renders better on GitHub - however, you can also use the PNG version by changing the file ending `.svg` to `.png`. Note that you can further customize the button's behavior through the use of [query string parameters](#query-string-parameters).

### Query string parameters

You can further customize the behavior of the **Deploy with balena** button by providing additional URL parameters. The following URL parameters are available and may be appended to the `https://dashboard.balena-cloud.com/deploy` link:

* `repoUrl` - The URL of the project repository. If you are placing the deploy button in a GitHub repo then balenaCloud can auto-determine the `repoUrl` from the referrer info in the HTTP headers. However on Firefox and with some ad-blockers this may fail. We recommend that you populate this query string parameter.
* `tarballUrl` - The URL of the project tarball. Automatically determined from `repoUrl` if not provided.
* `configUrl` - The URL of the configuration file for the fleet. Automatically determined from `repoUrl` if not provided.
* `defaultDeviceType` - The device type that will be pre-selected in the "Create fleet" modal. It defaults to Raspberry Pi 4 if not provided. You can find a list of [device types here](/reference/hardware/devices).

### balena.yml configuration file

Through the use of a `balena.yml` config file, you may also specify [configuration](/learn/manage/configuration) defaults and provide [variables](/learn/manage/variables). If provided, these are pre-populated in the advanced modal dialog when using the **Deploy with balena** button.

The `balena.yml` file can also be used to provide additional metadata to be used if the app is submitted to [balenaHub](https://hub.balena.io/).

The file should be named `balena.yml` and be located in the root of the project repository, or the `configUrl` link must be specified. A full example of the `balena.yml` file is shown below:

```yaml
name: balenaSound
type: sw.application
version: 3.5.2
description: >-
  Build a single or multi-room streamer for an existing audio device using a
  Raspberry Pi! Supports Bluetooth, Airplay and Spotify Connect
assets:
  repository:
    type: blob.asset
    data:
      url: 'https://github.com/balenalabs/balena-sound'
  logo:
    type: blob.asset
    data:
      url: >-
        https://raw.githubusercontent.com/balenalabs/balena-sound/master/logo.png
data:
  applicationEnvironmentVariables:
    - SOUND_VOLUME: 75
    - AUDIO_OUTPUT: AUTO
  defaultDeviceType: raspberry-pi
  supportedDeviceTypes:
    - raspberry-pi
    - raspberry-pi2
    - raspberrypi3
    - raspberrypi4-64
    - fincm3
    - intel-nuc
```

* `type` - Required field. In most cases this would be `sw.application`, unless you are implementing a block, in which case you need to use `sw.block`. For reference, check [balena.yml file for a block](/learn/develop/blocks#creating-your-own-block).
* `name` - A user-friendly name of your fleet.
* `description`: A description of what the fleet does. This is what is displayed if the fleet is published on [balenaHub](https://hub.balena.io/).
* `assets`
  * `<asset-slug>`: Supported values are `repository` and `logo`. The size of logo needs to be size 512 x 512 px
    * `type`: A fixed value that should be set to 'blob.asset'
    * `data`:
      * `url` - The URL of the asset that is being uploaded.
* `data`
  * `applicationEnvironmentVariables` - [Variables](/learn/manage/variables) allow you to provide runtime configuration without having to modify your source code.
  * `applicationConfigVariables` - [Configuration variables](/learn/manage/configuration) allow you to provide runtime configuration to the host OS and supervisor. These variables all begin with `BALENA_` or `RESIN_`.
  * `defaultDeviceType` - The device type that will be pre-selected in the "Create fleet" modal. It defaults to Raspberry Pi 4 if not provided. You can find a list of [device types](/reference/hardware/devices) here.
  * `supportedDeviceType` - The device types that the fleet supports. You can find a list of [device types](/reference/hardware/devices) here.
* `version` - A user-defined [semver version](https://semver.org/) for the release that is shown in the Version column of the Releases page of the balenaCloud web dashboard, and which may also be queried through the balena API `release.semver` field. If multiple deployments are made with the same version value, the balena API automatically increases the revision number in the format "1.2.3+rev1", "1.2.3+rev2", "1.2.3+rev3" and so on. Using version values that are **not** [semver compliant](https://semver.org/) is deprecated and may cause deployments to fail in the future. Currently, a deployment may succeed with such a non-compliant version value as long as the value is unique across all releases in the fleet, however the web dashboard will display version `0.0.0`.


# Manage


# Device statuses

Device statuses are displayed on the Devices page and the Device Summary page. An overview of the device statuses of a fleet is shown on the Fleets page. Each device can have one of the following statuses:

| Status                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Operational**           | The device is functioning normally and communicating with the cloud within the expected time interval. In the standard configuration, this means both [cloudlink](/learn/introduction/security#cloudlink) and the device heartbeat API are working. If [cloudlink is disabled](/reference/supervisor/bandwidth-reduction#side-effects-warnings), the device will still appear `Operational` if the heartbeat API is functional. |
| **Reduced Functionality** | The device is connected to the backend but is experiencing limited functionality due to either **missing recent Heartbeat API communications** or **lack of connection to cloudlink**.                                                                                                                                                                                                                                          |
| **Disconnected**          | The device is not connected to cloudlink and has not communicated via the Heartbeat API for a duration exceeding the [API polling interval](/learn/manage/configuration#variable-list). This status indicates that the device is completely unable to send or receive any data from the balena cloud.                                                                                                                           |
| **Configuring**           | The device is applying OS configuration. For example, an OS upgrade.                                                                                                                                                                                                                                                                                                                                                            |
| **Updating**              | The device is updating to a new App release. In future versions this will also reflect OS updates.                                                                                                                                                                                                                                                                                                                              |
| **Post Provisioning**     | The device has been [provisioned](/learn/introduction/primer#device-provisioning) but has not yet been booted from its internal storage (e.g. eMMC or NVMe).                                                                                                                                                                                                                                                                    |
| **Inactive**              | The device has been [deactivated](/learn/accounts/billing#inactive-devices) or has been [preregistered](https://docs.balena.io/learn/manage/pages/tCSZw6iQBfvGBg9ENzax#id-5.2-preregistering-a-device) but has not yet connected to the balenaCloud API.                                                                                                                                                                        |
| **Frozen**                | The device has been frozen because it's outside the organization's allowance, or is in a paid [fleet type](/learn/accounts/fleet-types) on a free tier organization.                                                                                                                                                                                                                                                            |

## Device Connectivity states

The balena device uses two mechanisms to maintain communication with balenaCloud, namely a periodic HTTP API heartbeat and a VPN based tunnel called cloudlink. The state of both of these links can be seen in the device listing.

<figure><img src="/files/J5XvdpGTtA6z2kOCEWaS" alt=""><figcaption></figcaption></figure>

`Reduced Functionality` indicates that the device is experiencing limited connectivity. This can be due to either **missing recent Heartbeat API communications** or **lack of connection to cloudlink**. The boolean columns for these states are as follows:

* **Cloudlink available, but heartbeat not**: The device is unable to communicate with the balenaCloud API. A device with cloudlink only is not able to apply any new changes made such as deploying new releases, applying service configuration values, or switching to local mode. However, since cloudlink is available, the device is accessible via SSH or the web terminal. When a device exhibits this state, the first troubleshooting step is to [run a healthcheck](/reference/diagnostics#device-health-checks) and pull [device diagnostics](/reference/diagnostics#device-diagnostics). This should help determine the reason the supervisor is not communicating with the balenaCloud backend.
* **Heartbeat available, but Cloudlink not**: The device is unable to connect to Cloudlink (e.g. a firewall is blocking VPN traffic). [Features enabled by Cloudlink](/learn/introduction/security#cloudlink) such as [SSH access](/learn/manage/ssh-access) will not be available. A device with Heartbeat Only status has internet connectivity, is able to reach the API, and can poll the cloud for new updates to apply, but actions that take immediate effect, such as purging data, restarting services, rebooting or shutting down, will not be available as they are performed via Cloudlink.

{% hint style="warning" %}
If the device is powered off or loses all network connectivity, the `heartbeat` indicator will show as connected (green) until enough time has passed to cover the device [API polling interval](/learn/manage/configuration#variable-list), at which time it will be marked as `Disconnected`.
{% endhint %}

## Update statuses

The `Update status` and `Update status duration` fields on devices represent the state of the current application update to target state.

{% hint style="warning" %}
Data for these states will only get populated for devices with [supervisor 16.7.0](https://github.com/balena-os/balena-supervisor/blob/master/CHANGELOG.md#v1670) or later.
{% endhint %}

| Status               | Description                                                                                                                                                                                                                                                            |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Done**             | The update, restart or configuration change is complete and the device is in its target state.                                                                                                                                                                         |
| **Downloading**      | The supervisor is downloading one or more container images associated with the target release                                                                                                                                                                          |
| **Downloaded**       | All container images in the target release have been downloaded. **Note:** If the device holds an update lock, it will stop in this state until the lock is released (depending on the [update strategy](/learn/deploy/release-strategy/update-strategies)).           |
| **Applying Changes** | The supervisor is performing actions to install the new release, i.e. killing old containers and making volumes/network/container changes.                                                                                                                             |
| **Rejected**         | The target release has required services that do not meet the [necessary requirements](/learn/develop/multicontainer#container-requirements) to run.                                                                                                                   |
| **Aborted**          | The supervisor has given up on trying to install a new release. There are currently no conditions under which the supervisor returns this state, but future work could allow the supervisor to abort an update, for instance, after a number of failed download tries. |

## Update Status Duration

This field is calculated based on the timestamp of the most recent update event. For example: In the screenshot above for Device Connectivity states, the device `bitter-wind` shows an update status duration of 17 minutes. This signifies that the device update status changed to `Downloaded` 17 minutes ago, which was the most recent update event. This value will reset when the update status changes again for the device. When querying this data from the API, you will receive a timestamp instead of a duration.

It is important to note that when the application starts up after a reboot or an app restart, this behavior is indistinguishable from an app installation. Consequently, the `Update Status Duration` timestamp will be refreshed whenever a reboot or restart occurs.

## Statuses and OS upgrades

The `Update status` currently focuses on application updates, and for the time being OS updates are still reflected as part of the device status. When a device is performing an OS update, the status will change to `Configuring` with additional details in parentheses, such as `Configuring (Update successful, rebooting)`. While filtering or searching based on the data in parentheses is not yet available, we are working towards unifying all update paths under the `Update Status` mechanism used by applications. This will make it even easier to track and manage updates in the future.

## Debugging Device Status

If you find your device to be displaying a status which is unclear even with the above notes, visit the [device debugging masterclass](/learn/more/masterclasses/device-debugging) for more information.




---

[Next Page](/llms-full.txt/1)

