> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirurobotics.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Linux

On Linux the Miru Agent runs as the `miru` system user and needs specific file system
permissions in the two cases where it touches files on your devices:

* **[Configs](#configs)** — writes config instances to disk when it deploys
  a release
* **[Data uploads](#data-uploads)** — reads files to upload them to your bucket

This page covers the agent's default permissions and how to grant file system access.

## Configs

**Default config path**

During installation, the agent creates and owns `/srv/miru`. The directory is owned by the `miru` user and group (`miru:miru`), with mode `0755`. The agent creates configs inside it with mode `0644` and subdirectories with mode `0755`.

| Account | Read | Write |
| - | - | - |
| Miru Agent (`miru`) | Yes | Yes |
| All other accounts | Yes | No |

Deploying configs to `/srv/miru` requires no additional configuration. The agent holds write access and all applications can read the configs.

<Info>
  `/srv/miru` is world-readable. For stricter security configurations, consider using a custom config path.
</Info>

**Custom config paths**

The Miru Agent also supports writing configs to arbitrary file system paths. Some examples
include:

* `/etc/myapp/configs/mobility.json`
* `/home/myapp/configs/communication.yaml`
* `/var/lib/myapp/configs/safety.yaml`

<Warning>
  You must use Miru Agent [v0.8.0](/changelog/agent#v0-8-0) or later to deploy
  configurations to a path that does not begin with `/srv/miru/config_instances/`.
</Warning>

To enable the agent to write to these paths, grant the [required permissions](#required-permissions) outlined
below. Otherwise, the agent will receive a permission denied error from the operating
system.

### Required permissions

To write to a given file, the `miru` user requires specific permissions to

1. The file itself
2. The directories along the path to the file

Let's consider the file `/var/lib/myapp/configs/planning.yaml` as an example. The
required read and write permissions to grant the `miru` user access to this file are
shown in the table below.

| Path | Permissions |
| - | - |
| `/var/lib/myapp/configs/planning.yaml` | read (`r`), write (`w`) |
| `/var/lib/myapp/configs` | read (`r`), write (`w`), execute (`x`) |
| `/var/lib/myapp` | execute (`x`) |
| `/var/lib` | execute (`x`) |
| `/var` | execute (`x`) |

To write to a given file, the `miru` user requires the following Unix permissions:

1. Read (`r`) and write (`w`) access to the *file* itself

   * `r` (read) is required to read the file contents.
   * `w` (write) is required to write the file contents.

   <Note>
     If the file does not yet exist, you can ignore this permission. The agent will
     create it with the appropriate permissions.
   </Note>

2. Read (`r`), write (`w`), and execute (`x`) access to the file's parent directory
   * `r` (read) is required to scan files within the directory.
   * `w` (write) is required to create/replace directory entries (e.g., temp file +
     rename for atomic writes).
   * `x` (execute/search) is required to access files within the directory.

3. Execute (`x`) access to all directories along the path to the file

   * `x` (execute) is required to access directories within the path to the file.

   <Info>
     Many directories, such as `/var/lib`, are world-readable by default and need no
     special permissions. Other directories, such as `/home/myapp`, will not grant
     `miru` user access by default and must be specifically configured.
   </Info>

To grant these permissions, follow the instructions in [Granting access](#granting-access).

## Data uploads

To upload files from disk, the agent **reads** the files matched by a [file
rule's](/data-uploads/concepts/file-rules/overview) `source.glob` and streams them to
your bucket.

You must grant the [required permissions](#required-permissions-2) outlined below. Otherwise, the agent will receive a permission denied error from the operating system.

### Required permissions

To read a file for upload, the `miru` user requires specific permissions to

1. The file itself
2. The directories along the path to the file

Let's consider a file rule whose `source.glob` is `/var/log/robot/*.log`, matching the
file `/var/log/robot/app.log`. The required permissions to grant the `miru` user access
to this file are shown in the table below.

| Path | Permissions |
| - | - |
| `/var/log/robot/app.log` | read (`r`) |
| `/var/log/robot` | read (`r`), execute (`x`) |
| `/var/log` | execute (`x`) |
| `/var` | execute (`x`) |

To read a given file, the `miru` user requires the following Unix permissions:

1. Read (`r`) access to the *file* itself

   * `r` (read) is required to read the file contents for upload.

2. Read (`r`) and execute (`x`) access to the file's parent directory

   * `r` (read) is required to list the directory and match files against the glob.
   * `x` (execute/search) is required to open files within the directory.

3. Execute (`x`) access to all directories along the path to the file

   * `x` (execute) is required to traverse directories within the path to the file.

   <Info>
     Many directories, such as `/var/log`, are world-readable and executable by default
     and need no special permissions. Others, such as `/home/myapp`, will not grant
     `miru` user access by default and must be specifically configured.
   </Info>

To grant these permissions, follow the instructions in [Granting access](#granting-access).

Uploads are read-only — the `miru` user does **not** need write access to the source
files, unless the rule also deletes them, covered next.

### Deleting local files

If a file rule has a [`retention`](/data-uploads/concepts/file-rules/rule-definition#retention) block,
the agent removes each matching file once its retention guarantee ends. Deleting a file
requires **write (`w`)** access to its **parent directory** (to remove the directory
entry), so grant the `miru` user `r`, `w`, and `x` on the directory in that case:

| Path | Permissions |
| - | - |
| `/var/log/robot/app.log` | read (`r`) |
| `/var/log/robot` | read (`r`), write (`w`), execute (`x`) |
| `/var/log` | execute (`x`) |
| `/var` | execute (`x`) |

To grant these permissions, follow the instructions in [Granting access](#granting-access).

## Granting access

There are two common methods for granting a user (the `miru` user) access to a given path:

1. Standard Unix permissions - basic owner/group/other mode bits on a file or directory
2. ACLs - per-user or per-group access rules beyond mode bits

Since standard Unix permissions are the most familiar, you'll likely find them simpler
to work with. We recommend starting here.

However, you may find that changing ownership or group is not possible or desirable. In
this case, ACLs may be a better fit. ACLs provide flexibility by allowing you to retain
existing permissions for a given path while granting the `miru` user or group the
required permissions.

### Standard Unix permissions

For standard Unix permissions, there are three approaches, in order of preference:

1. Add `miru` to a group that already has access
2. Grant the `miru` group the appropriate permissions
3. Transfer ownership to the `miru` user

When the target files already belong to a group with the access you need — common for
upload sources produced by another application — adding `miru` to that group is the least
invasive option.

We recommend starting there. Otherwise, grant the `miru` group access directly.

#### Add miru to an existing group

Add the `miru` user to a group that already has the required access, so it inherits that
group's permissions without touching the path:

```bash theme={null}
sudo usermod -aG <group> miru
```

The agent only picks up a new group when it starts, so restart it after adding the group:

```bash theme={null}
sudo systemctl restart miru
```

#### Set the group or owner

If no group already grants the access you need, set the path's group to `miru`
(recommended) or transfer ownership to `miru`.

**Files**

<Tabs>
  <Tab title="Group access">
    <CodeGroup>
      ```bash read (r) theme={null}
      path="/path/to/file.json"
      sudo chgrp miru $path
      sudo chmod g+r $path
      ```

      ```bash read-write (rw) theme={null}
      path="/path/to/file.json"
      sudo chgrp miru $path
      sudo chmod g+rw $path
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Transfer ownership">
    <CodeGroup>
      ```bash read (r) theme={null}
      path="/path/to/file.json"
      sudo chown miru $path
      sudo chmod u+r $path
      ```

      ```bash read-write (rw) theme={null}
      path="/path/to/file.json"
      sudo chown miru $path
      sudo chmod u+rw $path
      ```
    </CodeGroup>
  </Tab>
</Tabs>

<Info>
  Replace `path="/path/to/file.json"` with the actual file path
</Info>

**Directories**

<Tabs>
  <Tab title="Group access">
    <CodeGroup>
      ```bash read (rx) theme={null}
      path="/path/to/dir"
      sudo chgrp miru $path
      sudo chmod g+rx $path
      ```

      ```bash read-write (rwx) theme={null}
      path="/path/to/dir"
      sudo chgrp miru $path
      sudo chmod g+rwx $path
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Transfer ownership">
    <CodeGroup>
      ```bash read (rx) theme={null}
      path="/path/to/dir"
      sudo chown miru $path
      sudo chmod u+rx $path
      ```

      ```bash read-write (rwx) theme={null}
      path="/path/to/dir"
      sudo chown miru $path
      sudo chmod u+rwx $path
      ```
    </CodeGroup>
  </Tab>
</Tabs>

<Info>
  Replace `path="/path/to/dir"` with the actual directory path
</Info>

### ACLs

When you cannot change the ownership or the group of a path (e.g., a directory shared
between multiple services), use POSIX Access Control Lists (ACLs) for fine-grained
permission control.

ACLs require the `acl` package. If `setfacl` is not available, install it with:

```bash theme={null}
sudo apt install acl
```

**Files**

Grant the `miru` user access to a file.

<CodeGroup>
  ```bash read (r) theme={null}
  sudo setfacl -m u:miru:r /path/to/file.json
  ```

  ```bash read-write (rw) theme={null}
  sudo setfacl -m u:miru:rw /path/to/file.json
  ```
</CodeGroup>

<Info>
  Replace `/path/to/file.json` with the actual file path
</Info>

**Directories**

Grant the `miru` user access to a directory.

<CodeGroup>
  ```bash execute (x) theme={null}
  sudo setfacl -m u:miru:x /path/to/dir
  ```

  ```bash read (rx) theme={null}
  sudo setfacl -m u:miru:rx /path/to/dir
  ```

  ```bash read-write (rwx) theme={null}
  sudo setfacl -m u:miru:rwx /path/to/dir
  ```
</CodeGroup>

<Info>
  Replace `/path/to/dir` with the actual directory path
</Info>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.