# How to edit cloud-init files on the device or on an image file

The cloud-init **NoCloud** files live on the **boot partition**. On the running device they are at:

| File | Path on device |
|------|----------------|
| **user-data** | `/boot/firmware/user-data` |
| **meta-data** | `/boot/firmware/meta-data` |
| **network-config** | `/boot/firmware/network-config` |

They are owned by **root** and need **sudo** to edit.

---

## Method 1: Edit on the device over SSH

1. **SSH into the device** (e.g. via jump host):

   ```bash
   ssh -o ConnectTimeout=10 -J root@10.20.30.153 pi@10.20.50.147
   ```

2. **Edit with nano** (or `vi` if you prefer):

   ```bash
   sudo nano /boot/firmware/user-data
   sudo nano /boot/firmware/meta-data
   sudo nano /boot/firmware/network-config
   ```

3. **Save and exit:** in nano, `Ctrl+O` then Enter to save, `Ctrl+X` to exit.

4. **YAML:** use **spaces only** for indentation (no tabs). Wrong indentation can break cloud-init.

---

## Method 2: Copy to your PC, edit, copy back

1. **Copy from device to your PC** (from your project machine):

   ```bash
   scp -o ConnectTimeout=10 -J root@10.20.30.153 \
     pi@10.20.50.147:/boot/firmware/user-data   ./user-data
   scp -o ConnectTimeout=10 -J root@10.20.30.153 \
     pi@10.20.50.147:/boot/firmware/meta-data  ./meta-data
   scp -o ConnectTimeout=10 -J root@10.20.30.153 \
     pi@10.20.50.147:/boot/firmware/network-config ./network-config
   ```

   If you get "Permission denied" reading from `/boot/firmware/`, on the device run:  
   `sudo cp /boot/firmware/user-data /boot/firmware/meta-data /boot/firmware/network-config /tmp/ && sudo chmod 644 /tmp/user-data /tmp/meta-data /tmp/network-config`  
   then from your PC: `scp -J root@10.20.30.153 pi@10.20.50.147:/tmp/user-data ./user-data` (and same for meta-data, network-config).

2. **Edit** `user-data`, `meta-data`, and `network-config` on your PC.

3. **Copy back** (push from PC to device). Because the destination is root-owned, use a two-step on the device, or use root SSH:

   **Option A – copy to home then move with sudo:**

   ```bash
   # On your PC: copy to pi's home
   scp -o ConnectTimeout=10 -J root@10.20.30.153 ./user-data ./meta-data ./network-config \
     pi@10.20.50.147:~/

   # Then on the device (SSH in as pi):
   sudo cp ~/user-data ~/meta-data ~/network-config /boot/firmware/
   sudo chmod 644 /boot/firmware/user-data /boot/firmware/meta-data /boot/firmware/network-config
   ```

   **Option B – if you have root SSH to the device:**

   ```bash
   scp -o ConnectTimeout=10 -J root@10.20.30.153 ./user-data root@10.20.50.147:/boot/firmware/
   scp -o ConnectTimeout=10 -J root@10.20.30.153 ./meta-data root@10.20.50.147:/boot/firmware/
   scp -o ConnectTimeout=10 -J root@10.20.30.153 ./network-config root@10.20.50.147:/boot/firmware/
   ```

---

## Method 3: Edit on an image file (.img or .img.xz)

To edit cloud-init **inside a disk image** (e.g. `gnss-bootstrap-20260223-215010.img.xz`) without booting the device:

1. **Run the helper script** (requires `sudo` for loop device and mount):

   ```bash
   cd /path/to/reTerminal-DM4
   ./emmc-provisioning/scripts/edit-cloudinit-on-image.sh gnss-bootstrap-20260223-215010.img.xz
   ```

2. The script will:
   - Decompress the `.img.xz` (if needed; allow ~3GB free space and a minute or two)
   - Attach the image with `losetup` and mount the **boot** (FAT32) partition
   - Open your `$EDITOR` (or `nano`) on `user-data`, `meta-data`, and `network-config`
   - After you save and exit, unmount and recompress, **overwriting** the original `.img.xz`

3. **Back up the image** before running if you want to keep the original:
   ```bash
   cp gnss-bootstrap-20260223-215010.img.xz gnss-bootstrap-20260223-215010.img.xz.bak
   ```

4. **Options:**
   - `--no-recompress` — Leave the image decompressed after editing (do not overwrite the `.img.xz`).
   - `--replace-with-repo` — Copy `user-data`, `meta-data`, and `network-config` from `emmc-provisioning/cloud-init/` into the image before opening the editor (useful to start from repo templates).

---

## What to edit (typical)

- **meta-data**  
  - `instance_id`: change if you want cloud-init to treat this as a new instance (e.g. per device).  
  - Add `local-hostname: guard` (or your hostname) so the hostname is set on first boot.

- **user-data**  
  - Uncomment and set `hostname: ...` if you don’t use meta-data hostname.  
  - To run your **first-boot script** from the provisioning server, add a `runcmd` section that downloads and runs it (see `cloud-init/user-data-remote-gnss.example` in the repo).  
  - In that runcmd, set the **FILE_SERVER** URL to match your deployment network (e.g. `http://10.20.50.1:5000/files/first-boot` or your LXC IP).

- **network-config**  
  - Uncomment and adjust if you need static IP or specific WiFi; otherwise DHCP is usually enough.

---

## Example: minimal user-data that runs first-boot from your server

You can replace (or add to) the default template with something like this, and adjust the URL to your file server:

```yaml
#cloud-config
package_update: true
package_upgrade: false
packages: [curl]

runcmd:
  - curl -fsSL "http://10.20.50.1:5000/files/first-boot.sh" -o /tmp/first-boot.sh
  - curl -fsSL "http://10.20.50.1:5000/files/first-boot.conf" -o /tmp/first-boot.conf
  - chmod +x /tmp/first-boot.sh
  - /tmp/first-boot.sh
```

Full example with user, SSH, and optional first-boot config: **emmc-provisioning/cloud-init/user-data-remote-gnss.example**.

---

## After editing

- No reboot needed for the edits to “take effect”; they are just files on the boot partition.  
- When you **capture the image** (backup), the boot partition is included, so the updated `user-data`, `meta-data`, and `network-config` will be on the golden image.  
- On **first boot** after deploy, cloud-init reads these files and runs accordingly.
