Answers: <p>Even without Ansible or other config management tool, there's no
  reason any of those steps need to be manual: you could drive
  everything with a shell script, thus reaping all the benefits of
  automation: no more errors, consistent deployments, and faster
  configuration. Using Ansible can help make the process more modular
  and more structured, but it doesn't fundamentally allow you to do
  anything new.</p>
  <hr />
  <p>Ignoring the question of what tooling you use to drive the
  configuration, I'd like to suggest an option that you may not have
  considered: it's possible to perform all the configuration on the image <em>before</em> burning it onto a microsd card. You can mount the raspberry pi os image on a local directory, and then make all your configuration changes there. I use a process like this:</p>
  <ol>
  <li><p>Download and unzip the raspberry pi os image</p>
  </li>
  <li><p>Make a working copy of the image (this way you can re-use the base
  image multiple times to create different configured images):</p>
  <pre><code># cp 2022-01-28-raspios-bullseye-armhf-lite.img work.img
  </code></pre>
  <p>I like to extend the image a bit so there's room for installing
  new software:</p>
  <pre><code># truncate -s 2500MB work.img
  </code></pre>
  </li>
  <li><p>Attach the work image to a loop device:</p>
  <pre><code># losetup -fnP --show work.img
  /dev/loop0
  </code></pre>
  </li>
  <li><p>Grow the filesystem to use the additional space:</p>
  <pre><code># parted /dev/loop0 resizepart 2 100%
  # e2fsck -f /dev/loop0p2
  # resize2fs /dev/loop0p2
  </code></pre>
  </li>
  <li><p>Mount the filesystems locally:</p>
  <pre><code># mount /dev/loop0p2 /mnt
  # mount /dev/loop0p1 /mnt/boot
  </code></pre>
  </li>
  </ol>
  <hr />
  <p>Now you're in a position where you can create and modify configuration
  files on the image, in order to...</p>
  <ul>
  <li>Configure networking</li>
  <li>Configure the hostname</li>
  <li>Enable ssh</li>
  <li>Configure wifi</li>
  <li>Install ssh keys</li>
  <li>Etc.</li>
  </ul>
  <p>But what if you want to do other things, like update or install
  packages? If you install the <code>qemu-user-static</code> package and properly
  configure the <code>binfmt_misc</code> module (modern versions of the
  <code>qemu-user-static</code> package will do this for you automatically), you will be
  able to run Raspberry Pi binaries on your host. This allows you to run
  commands inside the image, like this:</p>
  <pre><code># systemd-nspawn -D /mnt apt update
  # systemd-nspawn -D /mnt apt upgrade -y
  # systemd-nspawn -D /mnt apt install -y git
  </code></pre>
  <p>Or inject a shell script:</p>
  <pre><code># systemd-nspawn -D /mnt --bind=$PWD/config.sh:/config.sh sh /config.sh
  </code></pre>
  <p>Here I'm using <code>systemd-nspawn</code>, which is a little like <code>chroot</code> (in
  this example), except it takes care of mounting special
  filesystems like /sys and /proc and has all sorts of interesting
  options (like the <code>--bind</code> option for bind mounting files or
  directories into the image).</p>
  <hr />
  <p>When you're all done, unmount the filesystem and disconnect the loop
  device:</p>
  <pre><code># umount /mnt/boot /mnt
  # losetup -d /dev/loop0
  </code></pre>
  <p>And write the customized image to an sd card:</p>
  <pre><code># dd if=work.img of=/dev/sdb bs=4M
  </code></pre>
  <hr />
  <p>You can wrap the entire process described here in a script, and have
  it take parameters to configure networking (specify a static address
  or use dhcp), etc.</p>
  
Answers: CC BY-SA 4.0
Answers: 2022-05-09T11:29:17.683Z
Answers: Thank you very much for your answer, this is very useful.
Answers: Postie
Answers: CC BY-SA 4.0
Answers: 2022-05-06T02:54:04.473Z
Answers: 2022-05-06T02:54:04.473Z
Answers: larsks
Body: <p>For multiple projects we are setting up 2 to 6 RPi's per project. Each project runs on a different network and for some of these networks we can use DHCP, for others the RPi's have to connect using a static IP address.</p>
  <p>Also every RPi needs a different hostname in sequential order. For instance for a project with three RPi's, the hostnames need to be PROCCESS1, PROCESS2, PROCESS3.</p>
  <p>All RPi's run the exact same software and every RPi has a single monitor connected.</p>
  <p>The current workflow is:</p>
  <ol>
  <li>Burn a prepared OS image for every RPi on a microSD</li>
  <li>Boot up the RPi using the microSD and manually set the hostname</li>
  <li>If needed, set the IP address to a static one</li>
  <li>Turn on the overlay file system so the system is read-only</li>
  <li>Repeat for the amount of RPi's needed</li>
  </ol>
  <p>This is a tedious task where errors are made and takes a lot of time. Step 1 can not be automated, since we don't have the hardware (altough the EtcherPro would eventually save a lot of time). Automating step 3 and 4 would be great if that can be realized. I've read a bit about Ansible and also encountered Chef and Puppet but I haven't dived into any of them yet.</p>
  <p>Is using Ansible with playbooks a good direction to develop further? Would it be possible to automate the setup using this tool? Is there a better/easier solution or would it not be possible at all? If someone has some tips or can guide in the right direction that would be great.</p>
  
Tags: <ansible><deployment><chef><raspberry-pi-os>
Title: Setup multiple Raspberry Pi different network configurations
UserDisplayName: Postie
ThreadText: # Setup multiple Raspberry Pi different network configurations
  
  (Asked by: username_0 on 2022-05-05)
  
  For multiple projects we are setting up 2 to 6 RPi's per project. Each project runs on a different network and for some of these networks we can use DHCP, for others the RPi's have to connect using a static IP address.
  
  Also every RPi needs a different hostname in sequential order. For instance for a project with three RPi's, the hostnames need to be PROCCESS1, PROCESS2, PROCESS3.
  
  All RPi's run the exact same software and every RPi has a single monitor connected.
  
  The current workflow is:
  
  1. Burn a prepared OS image for every RPi on a microSD
  2. Boot up the RPi using the microSD and manually set the hostname
  3. If needed, set the IP address to a static one
  4. Turn on the overlay file system so the system is read-only
  5. Repeat for the amount of RPi's needed
  
  This is a tedious task where errors are made and takes a lot of time. Step 1 can not be automated, since we don't have the hardware (altough the EtcherPro would eventually save a lot of time). Automating step 3 and 4 would be great if that can be realized. I've read a bit about Ansible and also encountered Chef and Puppet but I haven't dived into any of them yet.
  
  Is using Ansible with playbooks a good direction to develop further? Would it be possible to automate the setup using this tool? Is there a better/easier solution or would it not be possible at all? If someone has some tips or can guide in the right direction that would be great.
  
  **Tags:** ansible, deployment, chef, raspberry-pi-os
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2022-05-06. Score: 2 | Accepted answer
  
  Even without Ansible or other config management tool, there's no
  reason any of those steps need to be manual: you could drive
  everything with a shell script, thus reaping all the benefits of
  automation: no more errors, consistent deployments, and faster
  configuration. Using Ansible can help make the process more modular
  and more structured, but it doesn't fundamentally allow you to do
  anything new.
  
  ---
  
  Ignoring the question of what tooling you use to drive the
  configuration, I'd like to suggest an option that you may not have
  considered: it's possible to perform all the configuration on the image *before* burning it onto a microsd card. You can mount the raspberry pi os image on a local directory, and then make all your configuration changes there. I use a process like this:
  
  1. Download and unzip the raspberry pi os image
  2. Make a working copy of the image (this way you can re-use the base
     image multiple times to create different configured images):
  
     ```
     # cp 2022-01-28-raspios-bullseye-armhf-lite.img work.img
  
     ```
  
     I like to extend the image a bit so there's room for installing
     new software:
  
     ```
     # truncate -s 2500MB work.img
  
     ```
  3. Attach the work image to a loop device:
  
     ```
     # losetup -fnP --show work.img
     /dev/loop0
  
     ```
  4. Grow the filesystem to use the additional space:
  
     ```
     # parted /dev/loop0 resizepart 2 100%
     # e2fsck -f /dev/loop0p2
     # resize2fs /dev/loop0p2
  
     ```
  5. Mount the filesystems locally:
  
     ```
     # mount /dev/loop0p2 /mnt
     # mount /dev/loop0p1 /mnt/boot
  
     ```
  
  ---
  
  Now you're in a position where you can create and modify configuration
  files on the image, in order to...
  
  * Configure networking
  * Configure the hostname
  * Enable ssh
  * Configure wifi
  * Install ssh keys
  * Etc.
  
  But what if you want to do other things, like update or install
  packages? If you install the `qemu-user-static` package and properly
  configure the `binfmt_misc` module (modern versions of the
  `qemu-user-static` package will do this for you automatically), you will be
  able to run Raspberry Pi binaries on your host. This allows you to run
  commands inside the image, like this:
  
  ```
  # systemd-nspawn -D /mnt apt update
  # systemd-nspawn -D /mnt apt upgrade -y
  # systemd-nspawn -D /mnt apt install -y git
  
  ```
  
  Or inject a shell script:
  
  ```
  # systemd-nspawn -D /mnt --bind=$PWD/config.sh:/config.sh sh /config.sh
  
  ```
  
  Here I'm using `systemd-nspawn`, which is a little like `chroot` (in
  this example), except it takes care of mounting special
  filesystems like /sys and /proc and has all sorts of interesting
  options (like the `--bind` option for bind mounting files or
  directories into the image).
  
  ---
  
  When you're all done, unmount the filesystem and disconnect the loop
  device:
  
  ```
  # umount /mnt/boot /mnt
  # losetup -d /dev/loop0
  
  ```
  
  And write the customized image to an sd card:
  
  ```
  # dd if=work.img of=/dev/sdb bs=4M
  
  ```
  
  ---
  
  You can wrap the entire process described here in a script, and have
  it take parameters to configure networking (specify a static address
  or use dhcp), etc.
  
  > **Comments:**
  > **username_0**: Thank you very much for your answer, this is very useful.  
  
  ---
  
  