Miru Docs
Quickstart
Deploy your first software update with Miru!
Setup your development
Miru is the deployment infrastructure for robotics and IoT. Miru makes it easy to deploy software over-the-air to fleets of devices, anywhere in the world. Simply push new changes to GitHub and let Miru take care of the rest.
This Getting Started page will walk you through an example set up and deployment using Miru. Miru is compatible with any machine running an Ubuntu or Raspberry Pi operating system with an aarch64 or x86_64 architecture (32-bit architectures are not supported). Miru is particularly suited for NVIDIA Jetson devices, Raspberry Pis, and industrial PCs.
For requests for other devices/OS support, reach out to a founder. Do not use this in production without talking to a founder first!
Connect to GitHub
Miru integrates with your GitHub account for a seamless deployment experience. To begin, navigate to the integrations page in miru
by clicking the Integrations tab in the top left of the home page.
Before connecting your GitHub account, we’ll fork the Miru Examples repository to use throughout this getting started guide to show you how to deploy with miru
. We highly encourage you to follow along with us.
To use this repository with us, click Miru Examples repository and fork the repository by clicking the Fork button in the top right of the repository screen on GitHub.
Rename the repository to miru-examples and choose the owner as your personal GitHub account (we’re using mirueng). If using an organization’s account, the organization owner may need to grant you permission to fork the repository into the organization’s namespace and create a new repository.
You should now see the miru-examples repository on your GitHub account.
Navigate back to the integrations page in Miru and click Connect to connect your GitHub account.
Select the GitHub account that you just created the repository with. For us, that’s miru-eng.
Select the miru-examples repository to grant Miru access and click Save. You can add other repositories or change Miru’s access to your GitHub repositories at any time. If you’re adding Miru under an GitHub organization account, the organization owner may need to grant Miru access themselves.
After the installation completes, you’ll be redirected to the integrations page in Miru. Wait a few seconds before refreshing the page to see your updated repository access.
After connecting a GitHub repository, you’ll need to create a GitHub Source. A GitHub Source is uniquely identified by three items:
- Repository - the GitHub repository (ex: miru-examples)
- Branch - the branch for the repository (ex: main)
- Build Directory - the folder in the repository housing a docker-compose.yaml file (ex: /backend)
Note that you can create multiple sources from the same repository, provided each source has a unique branch and build directory combination.
To create a GitHub source, click the Source button, fill in the fields,
and click Create Source. We’ll set up our GitHub source to track the
\todo
in the main
branch of our forked miru-examples
repository and name
the source To Do.
The default architecture for a new GitHub source is aarch64. However, you can also use x86_64 as well. GitHub sources with an aarch64 architecture will create artifacts supported for 64-bit ARM devices (NVIDIA Jetson, Raspberry Pi, etc.) while GitHub sources with an x86_64 architecture will create artifacts supported for 64-bit x86 machines (e.g. industrial PCs)
Create a Device
Navigate to the devices page and create a Device Group. Device Groups are a convenient way to organize your devices. You might create a group for a specific functionality, different customers, a set of test devices, etc.
In general, device groups are meant to organize your devices. You can use devices of different hardware types (NVIDIA Jetson, Raspberry Pi, etc.) in the same group as well easily move devices between groups later if you’d like.
Each Device Group is connected to one or more GitHub sources. This allows you to use multiple GitHub sources (from potentially different repositories) to deploy code to your devices. On the other hand, you can use the same GitHub sources across different groups so that groups or organized by customer or region, but the devices in the group still have the same code being deployed to them.
When creating a Device Group, simply name the group and select the GitHub Source. We’ll name ours Example Group and set the GitHub Source to be the To Do source we just created.
First click into the Device Group you want to add your device to. We’ll use the Development Group.
Click the Device button in the top right-hand corner.
Simply fill in the prompted information to name your device, choose the hardware, etc. Don’t stress about getting it right the first time, you can easily change this information later.
To edit a device, find the device on the Group page and click the ellipsis on the far right. Then select the “Edit” button.
From you here you can change the device’s group, edit it’s name, or select a different hardware.
Install Miru onto your Device
Installing Miru onto your device takes 3 minutes. The only dependencies for Miru are docker
, docker compose
, and miru
. If you don’t have docker
or docker compose
installed already don’t worry, Miru will handle the installation for you!
We highly recommend to SSH into your device so that you can easily copy and paste your authentication token from your local computer.
Please note that miru
is compatible with any machine running an Ubuntu or Raspberry Pi operating system with an aarch64 or x86_64 architecture (32-bit architectures are not supported). Miru is particularly suited for NVIDIA Jetson devices, Raspberry Pis, and industrial PCs.
1. Install miru
Run the following command to install miru
, which will download and execute this installation script.
curl https://api.miruml.com/v1/install.sh -sSf | sudo /bin/sh
curl
: curl is a command-line tool used to transfer data from or to a server. In this case we’re using it to download the miru
installation script shell script from the Miru servers to your local computer.
Install it with the following two commands:
sudo apt-get update
sudo apt-get install curl
http://api.miruml.com/v1/install.sh
: The URL which resolves to the Miru servers for the curl requests
: Runscurl
in silent mode, suppressing progress and error messages.S
: In combination withs
, it makescurl
show error messages if any occur.f
: Makescurl
fail silently (without outputting the body) on server errors (e.g., 404 or 500 HTTP status codes).|
(pipe): The pipe (|
) is a Unix command that takes the output of the command on its left (in this case, the output ofcurl
) and uses it as the input to the command on its right.sudo
: Runs the following command (/bin/bash
) with superuser (root) privileges. This is needed to installmiru
as a Debian package/bin/sh
: The Shell, which is used to execute themiru
installation script on your local system.
If you don’t have docker installed already, don’t worry. Miru will handle the installation for you. First, select the OS your device is running on. Currently, Miru only supports Ubuntu.
? We’ve autodetected your operating system to be Ubuntu.
Please confirm this selection or, if this is incorrect, please select your operating system from the list below:
❯ Ubuntu
Raspberry Pi
Other
The miru
installer will quickly test if Docker is installed on your device and if it is compatible with miru
.
Miru requires Docker and Docker Compose (Version 2!)
To ensure compatibility with Miru, we will quickly test your Docker installation with our software
\ Testing Docker Installation
If Docker is not installed or is not compatible with miru
, you’ll be asked to let the miru
installer install/upgrade Docker for you. This is done using this bash script, which executes the Official Docker Installation Instructions for the OS your device is running on.
If you’re upgrading your Docker installation, existing Docker resources (containers, images, networks, etc.) will be left untouched and will continue running after the installation is complete.
Once the bash script completes, the miru
installer will again test if the Docker installation is compatible (which it should be), after which it will automatically move on to authenticating your device.
To authenticate your device, navigate to the group your device lives in and select the device you want to authenticate. Click the key icon at the far right of the device’s row to retrieve its authentication token.
A short-lived token will be granted to you.
Copy and paste this token into the Enter your Authentication Token prompt on your device.
To authenticate your device, you'll need to retrieve its
authentication token from the Miru Web Application.
? Enter your Authentication Token › eyJhbGciOiJIUzI...
After entering your authentication token and successful authentication, your device is ready to deploy with miru
!
Create an Artifact
Miru utilizes Docker Compose to deploy your application. This section will walk through the setup of your application with Docker Compose to deploy to miru
. We’ll use the Miru Examples repository you forked in the Connect to GitHub section.
Ensure you’re using a development machine for this section. This should be a computer that has pull/push access to your GitHub account. We recommend using a computer different from the device you installed miru
onto. Although, you could use the same device if that’s all you have access to.
First clone your miru-examples repository.
# your repo url should like similar to: https://github.com/<your-username>/miru-examples.git
# ours is https://github.com/miru-eng/miru-examples.git when using the 'miru-eng' account
git clone YOUR-MIRU-EXAMPLE-REPOSITORY-URL
Navigate inside the miru-examples directory.
cd miru-examples
Your directory structure should look similar to the following:
miru-examples/
├── todo/
│ └── ...
├── simple-torch/
│ └── ...
└── ...
Open the /todo directory in your favorite code editor to examine the code and containers that will be deployed onto your device. While there are other folders within the miru-examples repository, we setup a singel GitHub Source in our Device Group, which looks at the todo folder. This was specified by inputting the build path as /todo when creating the Device Group.
The todo folder has the following structure:
todo/
├── compose.yaml
├── backend/
│ ├── Dockerfile
│ ├── ...
└── frontend/
├── Dockerfile
├── ...
The first (and maybe most important) file is the compose.yaml
file. This specifies what docker services (containers) to run, how they should interact with the host machine, and how to build or pull the images these services will run.
name: todo
services:
frontend:
build:
context: frontend
target: development
ports:
- 3000:3000
stdin_open: true
volumes:
- /usr/src/app/node_modules
restart: always
networks:
- react-express
depends_on:
- backend
backend:
restart: always
build:
context: backend
target: development
volumes:
- /usr/src/app/node_modules
depends_on:
- mongo
networks:
- express-mongo
- react-express
expose:
- 3000
mongo:
restart: always
image: mongo:4.2.0
volumes:
- mongo_data:/data/db
networks:
- express-mongo
expose:
- 27017
networks:
react-express:
express-mongo:
volumes:
mongo_data:
For example, the frontend service contains the following build specification:
frontend:
build:
context: frontend
target: development
...
The frontend.build
parameters specify where the Dockerfile for this service is located in the filesystem and any information required to build the Docker image.
The frontend.build.context
parameter tells Docker Compose to look inside the frontend directory that is located within the parent directory of the compose.yaml file’s parent directory. For example, since the compose.yaml file’s path is /todo/compose.yaml, Docker Compose will look for a Dockerfile at /todo/frontend/Dockerfile.
Similarly, the backend service’s build specification is:
backend:
build:
context: backend
target: development
So Docker Compose will look for the backend service’s Dockerfile at /todo/backend/Dockerfile
. If you look within these folders you’ll find Dockerfiles in each of them.
todo/
│
├── compose.yaml
├── backend/
│ ├── Dockerfile
│ └── ...
└── frontend/
├── Dockerfile
└── ...
The Dockerfiles specify how to build their respective service (frontend or backend) into a Docker image. This process is crucial for creating a consistent and reproducible environment for the application.
The mongo service is the last service defined in the compose.yaml file. Notably, it does not have a build parameter. Instead, it uses an image parameter (mongo:4.2.0) to specify the Docker image to pull from Docker Hub. This approach ensures that the service uses a specific version of the MongoDB image.
mongo:
restart: always
image: mongo:4.2.0
These services work together to create a simple web application that can be accessed on localhost to create a ToDo list. After deploying this application, you will be able to navigate to localhost on the device in which the application is deployed and see the following:
To use miru
with your docker compose setup, simply ensure your docker-compose.yml is located in the directory specified by your GitHub Source. For us that would be …/miru-examples/todo/compose.yml since we specified our GitHub Source directory to be /todo and our repository lives in the miru-examples directory. Your compose file can be named compose or docker-compose with a file extension of yaml or yml (compose.yml, compose.yaml, docker-compose.yml, or docker-compose.yaml).
Ensure you’re using a development machine for this section. This should be a computer that has pull/push access to your GitHub account. We recommend using a computer different from the device you installed miru
onto. Although, you could use the same device if that’s all you have access to.
With our application ready, we’ll navigate back to our miru-examples repository, add a change, and push to GitHub.
# This is an arbitrary change to push a new commit to GitHub
# Feel free to push whatever arbitrary change you'd like
echo "Hello Miru!" >> miru.txt
git add .
git commit -m "Test Miru deployment"
Upon pushing to GitHub, Miru receives the push event and begins building your containers on our servers. You’ll be able to see the progress of this Artifact being built on the Group page the device is located in.
Your artifact will transition through 5 different states before it is ready for deployment.
- Queued -> Waiting for a build server to become available to build your artifact
- Verifying -> Verifying your Docker Compose file and build specifications are valid
- Building -> Building your Docker images
- Storing -> Storing your images in our private container registry
- Ready -> The artifact is ready to be deployed to your devices.
At the top of a group’s page, you’ll find Staged Artifacts. These are the artifacts which are available to deploy to your devices. By default, newly created artifacts are placed in the staging area and are NOT deployed to your devices. Deployments only occur if you explicitly do so via the UI (more on this in later sections).
For convenience, you can see the artifact’s ID, Git commit, and GitHub source. To see more information about an artifact, click on the artifact’s ID. Alternatively, click the ellipsis on the far right and select “Inspect”. To move an artifact out of the staging area, select the “Archive” option after clicking the ellipsis for that artifact.
Archived artifacts can be found on the Artifacts page within a group (top left next the Group page). Here you can see the history of all artifacts, including staged artifacts, for a given group. You can easily sort and search them for more information. If you want to put an artifact back in the staging area, click the ellipsis on the far right and select “Restage”.
If we inspect an artifact (click on it’s ID), we’ll see all the information about it including the miru
and Docker build logs. This is will give you any necessary troubleshooting information if the build fails for some reason.
You can also easily reference the build logs to know what was in your Dockerfiles as well as examine the steps our build servers executed to create your artifact.
Deploy an Artifact
To deploy an artifact to your devices, click the ellipsis on the far right of the artifact you want to deploy and select “Deploy” from the dropdown menu.
If a deployment currently on a device is from an artifact with the same GitHub source as the artifact being deployed, then the new deployment will replace this old deployment.
A popup will appear, allowing you to select which devices you would like to deploy the artifact to. Device’s with a deployment already running the chosen artifact will not appear (since the artifact is already deployed).
For example, consider Artifact A and Artifact B, which both have the same GitHub Source C. If a device has a deployment running Artifact A and we’re deploying Artifact B, the new deployment running Artifact B will replace the deployment running Artifact A. However, if Artifact B has GitHub Source D (instead of GitHub Source C), then the new deployment running Artifact B will simply deploy alongside the deployment running Artifact A (devices can run more than one deployment).
After selecting the devices to deploy to and clicking “Deploy”, the deployments will be queued, awaiting the devices to notice the new deployment and take appropriate action.
Scrolling down to the Devices portion of the Group page, you’ll find a preview of the information about the device. An overall device status as well as a count of the deployments and their containers are shown for convenience.
Clicking on the name of a device, we can see more detailed information, including the state of its deployments and containers. Each deployment shows its state (queued, downloading, running, etc.), the artifact ID it is running, the deployment ID, and the GitHub Source. By clicking the ellipsis for a deployment, you can start, stop, or remove a deployment from that device.
Scrolling down you’ll find all the containers on the device. Again, clicking the ellipsis will allow you to start or stop a given container from the convenience of our UI.
To verify the deployment is running your device, open the terminal on your device and view its containers.
docker ps
You should see 3 containers: a backend, a frontend, and mongo (the redis container is irrelevant here).
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0acc0567aa05 redis:7.2.5 "docker-entrypoint.s…" 19 hours ago Up 21 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp miru-backend-database-1
7eb4db606f1a 008971674194.dkr.ecr.us-east-1.amazonaws.com/frontend-47:05acb0845046f7cb42116fb7a22978762a4c8ceb "docker-entrypoint.s…" 2 days ago Restarting (1) 21 seconds ago miru-todo-frontend-1
a9248d812f66 008971674194.dkr.ecr.us-east-1.amazonaws.com/backend-47:05acb0845046f7cb42116fb7a22978762a4c8ceb "docker-entrypoint.s…" 2 days ago Restarting (1) 18 seconds ago miru-todo-backend-1
2d231e06c705 mongo "docker-entrypoint.s…" 2 days ago Up 21 minutes 27017/tcp miru-todo-mongo-1
Furthermore, you should see these exact same containers in the miru
UI for this device as well.
If you have access to your device’s browser you can navigate to localhost and view the Todo application running on your device.
Congratulations! You’ve made your first OTA deployment with Miru.
To see more information about a deployment, click on its ID (the rocket ship icon).
This will take you to the deployment page, where you can see the error logs for that deployment. We’re working on adding more logs for both the deployments and their containers!
To see the deployment history for a device, click the Deployments tab in the top left corner when viewing the device page. From here you’ll be able to search all the deployments for this device. If you would like to redeploy a deployment, click the ellipsis for that deployment and select Redeploy.
Connect to DockerHub [Optional]
Instead of using public Docker Hub images like we did with mongo:4.2.0
image in Prepare your Application, you can use images from your private Docker Hub repository. Navigate to the integrations page in miru
by clicking the Integrations tab in the top left of the home page.
Navigate to the Docker Hub Integration using the options on the left and create an access token for miru
to connect to your repository with.
Navigate to the personal access tokens page located in your Docker Hub account settings. Generate a new personal access token to grant miru
. Ensure you select Read-only NOT Public Repo Read-only to grant miru access to images in your private repository.
Enter your username and personal access token into miru.
Congratulations! You’ve successfully connected miru
with your Docker Hub. miru
will have read-only access to images in your private repository. If using repositories from an organization with miru
, please ensure your account (that you created the personal access token with) has the necessary permissions to use such repositories.
To use an image from private repositories, simple specify the image reference for your Docker image in your docker-compose.yml file.
<compose-service>:
image: <namespace>/<repository>:<tag>