<message>Update the _set_golden_from_path function to improve the handling of existing golden image files. Replace the existing unlink logic with a more robust method that safely removes files or broken symlinks using the missing_ok parameter. This change enhances the reliability of the backup upload process by ensuring that stale references are properly cleared before setting a new golden image path.
122 lines
4.5 KiB
Markdown
122 lines
4.5 KiB
Markdown
# How to edit cloud-init files on the device before capturing the image
|
||
|
||
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/
|
||
```
|
||
|
||
---
|
||
|
||
## 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.
|