# Create custom FreeBSD .img from original FreeBSD-13.0-RELEASE-amd64-memstick.img



## fumanchu (Jul 20, 2021)

Hello,

I am looking at taking the original FreeBSD-13.0-RELEASE-amd64-memstick.img image file, mounting it, adding a few new .sh scripts, and then creating a new bootable .img file.  I am changing nothing else...

I have been able to mount the original .img using the following commands...


```
$ mdconfig -a -t vnode -f /path/to/FreeBSD-11.0-RELEASE-amd64-mini-memstick.img -o readonly -u 0
$ mount -r /dev/md0s2a /mnt
```

I have then created a directory and added my .sh scripts...

And then I have been able to unmount using the following commands...


```
$ umount /mnt
$ mdconfig -d -u 0
```

I am stuck at how to create the new bootable .img file...

Thoughts?


----------



## T-Daemon (Jul 20, 2021)

You don't need to create a new bootable .img file. The one you have added scripts to is good for use.


----------



## Phishfry (Jul 20, 2021)

It is even possible to grow the image by dd'ing zeros to the image file and then mount your image via memory disk and use tools to grow the partition and filesystem mounted in your memory disk..
UFS has a good amount of padding so you can add some files to the stock image.


----------



## obsigna (Jul 21, 2021)

While it is correct what T-Daemon and Phishfry said, you need to omit the readonly flags on your respective commands, since otherwise, I doubt that anything becomes written to the image.

`mdconfig -a -u 0 -t vnode -f /path/to/FreeBSD-11.0-RELEASE-amd64-mini-memstick.img`
`mount /dev/md0s2a /mnt`


----------



## Phishfry (Jul 21, 2021)

I should mention if you expand an image (with zeros) that uses a GPT filesystem scheme you will need to run gpart recover.
GPT puts a boot record at begining of disk and at the end. When you expand a GPT image you lose the GPT in the last sectors. So `gpart recover ${DISK_NAME}` will fix it when mounted as Memory Disk.


----------



## fumanchu (Jul 21, 2021)

Thanks for the great information... I am really new at all this so please bear with me...

As T_Daemon mentioned, I would not have to create a new .img as I can simply use the one I already have.  I am a bit confused on that statement...  I assume that once I unmount /mnt, the original .img is automatically updated with my changes?  If that is true, that is pretty cool...

Then as Phishfry mentioned, it is possible to grow image... I assume this is only needed if I add enough new stuff to the original .img file that it's original size would be exceeded?  If I simple added a couple small .sh scripts, the original .img size would most likely not be exceeded; where as, if I added a full blown package, say something like vim, the new size of the .img would be exceeded so I would have to expand the size?  If this is true, I will need to dig into how to expand the .img as Phishyfry also mentioned.


----------



## SirDice (Jul 21, 2021)

fumanchu said:


> I assume that once I unmount /mnt, the original .img is automatically updated with my changes? If that is true, that is pretty cool...


Yes. It's an image of a disk, mdconfig(8) makes it so you can access it as if it was a 'real'  disk.



fumanchu said:


> Then as Phishfry mentioned, it is possible to grow image... I assume this is only needed if I add enough new stuff to the original .img file that it's original size would be exceeded?


Yes, the image is relatively small. So you could run out of disk space on it.


----------



## Phishfry (Jul 21, 2021)

Think of the IMG file as an container. You can grow this container and adjust the filesystems to suit.



fumanchu said:


> I assume this is only needed if I add enough new stuff to the original .img file that it's original size would be exceeded?


Yes that is true.
Use `df -h` to see how full the container gets.
UFS has around 7% padding so you could theoretically see up to 107% disk usage.
In reality you never want to get it that full. Maybe 105%. Very ill consequences if you meet the real end of disk.


----------



## fumanchu (Jul 21, 2021)

Many thanks for the great information!  I will give this all a try.


----------



## fumanchu (Jul 23, 2021)

So far so good as I am to the part where I now need to expand the memory disk to the new size as the files that I need to add definitely cause an out of disk space error...

Is there somewhere I can be pointed to for information on how to expand the memory disk?  I have tried gpart's resize command; however, that does not seem to work... well I might not be using it correctly...

When I try gpart, I get this...


```
$ mdconfig -a -t vnode -f $HOME/FreeBSD-13.0-RELEASE-amd64-memstick.img -u 0
$ gpart show /dev/md0
->       1  2130664  md0  MBR   (1.0G)
         1    66584    1  efi   (33M)
     66585  2064080    2  freebsd  [active]  (1.0G)
```

I assume that I need to expand the freebsd subpartition...


----------



## T-Daemon (Jul 23, 2021)

fumanchu said:


> Is there somewhere I can be pointed to for information on how to expand the memory disk? I have tried gpart's resize command; however, that does not seem to work...


You need first to increase the size of the image before resizing it with gpart(8). See truncate(1).



fumanchu said:


> I assume that I need to expand the freebsd subpartition...


You need to resize (expand) two times.

The partition scheme and partition structure of the installer image (FreeBSD calls MBR partitions slices, slices can have partitions):

```
MBR                                         md0
slice 1       efi                           md0s1
slice 2       freebsd                       md0s2
        BSD partition scheme                md0s2
        slice 2 partition 1  freebsd-ufs    md0s2a
```

This is the order of commands to increase the size of the FreeBSD installer image:

```
truncate -s +<size>m FreeBSD-...img  # m = Megabyte see truncate(1)

mdconfig  -u 0 FreeBSD-...img   # You can skip all other options, even '-u 0'.
                                # See 'mdconfig file' in mdconfig(8).

gpart resize -i 2 md0
gpart resize -i 1 md0s2

growfs md0s2a

mount /dev/md0s2a /mnt
Add files
umount /mnt

mdconfig -du 0
```
Image ready for use

For details see the manuals of the commands.


----------



## fumanchu (Jul 23, 2021)

Many thanks!  I will give that a try and report back...


----------



## Phishfry (Jul 23, 2021)

Truncate should work but in the past I have just dd'ed zeros to the tail end of the file.








						VM File sizing
					

I am new to VM's so I wonder what is the best strategy for VM file sizing. For example I am building a Poudiere VM and I truncated my VM for 80GB. What if I need more later? Can I DD my VM image into another larger image and grow the filesystem on the VM side? So I can probably grow a VM but...




					forums.freebsd.org
				




This shows VM image manipulation. Same concept.


----------



## fumanchu (Jul 26, 2021)

Okay, reporting back my results.

I am able to add my files to the the .img; however, when I try and use this .img to install FreeBSD, I do not have my files installed.

What I have done:

I downloaded FreeBSD-13.0-RELEASE-amd64-memstick.img.
I copied FreeBSD-13.0-RELEASE-amd64-memstick.img to FreeBSD-13.0-RELEASE-amd64-memstick-NEW.img
Installed *portupdate *package using 
	
	



```
pkg install portupgrade
```

Used the *pkg_fetch *command to download the necessary packages including all their dependencies.  By default the packages are downloaded to _/usr/ports/packages._
After downloading all the packages, I calculated the size.
I then used the *truncate *command to increase the size of the .img by that amount 
	
	



```
truncate -s +130m FreeBSD-13.0-RELEASE-amd64-memstick-NEW.img
```

I then created a memory disk from the .img 
	
	



```
mdconfig -u 0 FreeBSD-13.0-RELEASE-amd64-memstick-NEW.img
```

I then ran *gpart *on each of the partitions
	
	



```
gpart resize -i 2md0
```


```
gpart resize -i 1 md0s2
```

I then grew the filesystem using the *growfs *command 
	
	



```
growfs md0s2a
```

Next, I mounted the memory disk using the mount command 
	
	



```
mount /dev/md0s2a /mnt
```

Next, I went to the_ /mnt/us_r and created a new directory for the packages I had downloaded
	
	



```
cd /mnt/usr
```


```
mkdir packages
```

Next, I copied the files from _/usr/ports/packages_ to _/mnt/usr/packages_

```
cp /usr/ports/packages /mnt/usr/packages
```

Next, I umounted the memory disk
	
	



```
umount /mnt
```

Next, I removed the memory disk
	
	



```
mdconfig -du 0
```

After all this I created the memory disk from the NEW.img as well as mounted it to /mnt again just to make sure my files were then and sure enough, they were.  However, when I attempt to install FreeBSD from this new .img, my /usr/packages directory and files does not exist on the machine...

Any idea?


----------



## T-Daemon (Jul 26, 2021)

fumanchu said:


> 4. Used the *pkg_fetch *command to download the necessary packages including all their dependencies. *By default the packages are downloaded to *_*/usr/ports/packages.*_


Not related to the problem: By default pkg-fetch(8) places fetched packages in internal cache (/var/cache/pkg), unless '-o <destdir>' is given as option.



fumanchu said:


> However, when I attempt to install FreeBSD from this new .img, my /usr/packages directory and files does not exist on the machine


I can't reproduce missing /usr/packages directory and files on installation image. After executing all steps and dd(1)'ing the .img on a USB stick and mounting or booting it, the directory and files are at their places.

Are you sure you copied the *-NEW.img on installation media, not an original, unmodified image?


----------



## fumanchu (Jul 27, 2021)

I will check again in the morning and report my findings.  I am pretty sure I copied the -NEW.image but I could be mistaken.


----------



## Phishfry (Jul 27, 2021)

T-Daemon said:


> By default pkg-fetch(8) places fetched packages in internal cache (/var/cache/pkg), unless '-o <destdir>' is given as option.


And even if you specify a directory with "-o" the package files actually end up in -o <destdir/All>


----------



## fumanchu (Jul 27, 2021)

Okay, here is what I did to confirm that my files are not transferred to a fresh install...

I copied the -NEW.image onto a flash-drive.
I took that flash-drive to another FreeBSD machine, created the memory disk, mount it, and looked at its contents.
All my custom files were indeed there! 
I then burned that confirmed image onto a new flash-drive so I can boot from it.
For grins, I mounted the newly burned flash-drive and took a look at the contents to make sure my custom files were still there... They were! 
I then booted another machine using that flash-drive and installed a fresh copy if FreeBSD...
After the install finished, I took a look at the new install to see if my custom files were there... They were not! 
Not sure what I missed.  Maybe the actual FreeBSD installer is not picking up my custom files for some reason...  More investigation needed...


----------



## T-Daemon (Jul 27, 2021)

fumanchu said:


> Okay, here is what I did to confirm that my files are not transferred to a fresh install...
> ...
> 6. I then booted another machine using that flash-drive and installed a fresh copy if FreeBSD...
> 7. After the install finished, I took a look at the new install to see if my custom files were there... They were not!


Until now I was under the impression we are talking about the presents of files (packages) on the installation image, not about a automated director creation on the newly installed system and transfer of packages (custom files) there from the installation media.



fumanchu said:


> Maybe the actual FreeBSD installer is not picking up my custom files for some reason...


There is no bsdinstall(8) menus installation procedure that creates automatic a package directory on the target system and initiates a transfer of custom files.

If you want that you need to do it manually or scripted (see SCRIPTING in bsdinstall(8).


----------



## fumanchu (Jul 27, 2021)

Hum...

Since our users may or may not have Internet access, they can simply take this modified bootable memstick image, burn it on a flash/thumb drive, stick in into a machine, boot from it, and go through the normal installation process.  My plan was that the installer (or whatever it is called) would have simply copied my files to the destination drive since they are already inside the image alongside all the other files...  I would then instruct the user, via documentation, on how to run the custom script.  This script that they would run would install all the pre-downloaded packages as well as perform other tasks like, create a pre-defined user, harden the operating as needed, etc.


----------



## T-Daemon (Jul 28, 2021)

fumanchu said:


> My plan was that the installer (or whatever it is called) would have simply copied my files to the destination drive since they are already inside the image alongside all the other files...


That's not how the installer (bsdinstall(8)) works. The new systems base and kernel are not copied from the installer images file system but extracted from /usr/freebsd-dist/base.txz and kernel.txz.



fumanchu said:


> I would then instruct the user, via documentation, on how to run the custom script. This script that they would run would install all the pre-downloaded packages ...


Can't the script install pre-downloaded packages from $INSTALLER_IMAGE/usr/packages instead of $NEW_SYSTEM/usr/packages?


If you insist on having a $NEW_SYSTEM/usr/packages/*txz directory and files, unless nobody else has a better idea, you could manipulate $INSTALLER_IMAGE/usr/freebsd-dist/base.txz.

Follow steps bellow as root, assuming a memory disk is created from *memstick.img and file system mounted:

```
cd /tmp
mkdir a
mv /mnt/usr/freebsd-dist/base.txz  .

tar xf base.txz -C a
mkdir a/usr/packages
cp /usr/ports/packages/* a/usr/packages

cd a
tar acf /mnt/usr/freebsd-dist/base.txz  .  

cd /mnt/usr/freebsd-dist
rm MANIFEST
sh /usr/src/release/scripts/make-manifest.sh  *.txz  >  MANIFEST

umount ...
mdconfig ...
```


----------



## fumanchu (Jul 28, 2021)

What you suggested looks interesting...  I can look into this...

I have found this link which looks interested...  I wonder if this with work... https://forums.freebsd.org/threads/how-is-bsdinstall-started.80352/


----------



## T-Daemon (Jul 28, 2021)

That won't work, it won't create $NEW_SYSTEM/usr/packages/*.txz. If you want them there the only way to do that, as I see it, is to add the pre-downloaded packages in base.txz. When the new system is installed from there it will have the packages directory and files.


----------



## T-Daemon (Jul 28, 2021)

Ah, sorry, that works too. I recalled it otherwise. What am I talking. It won't work. Sorry, I hadn't much sleep last night, someone close to me has passed away.


----------



## fumanchu (Jul 28, 2021)

No problem.  I totally understand the lack of sleep issue.

I am looking into your proposed solution with modifying_ base.txz_...


----------



## fumanchu (Jul 30, 2021)

Okay, I took your suggestion and updated the_ base.txz_ file with my updated packages.  That was fairly easy to accomplish... except I am not getting the attached error when during installation...  I will start over and see if I can reproduce this...


----------



## T-Daemon (Jul 30, 2021)

No problem here. The installation image with additional binary packages in base.txz included, copied on a USB stick, does install without any errors.


----------



## fumanchu (Jul 30, 2021)

Okay, I redid the steps and recreated the .img file.  This time when I did the installation, I did not get that error... So that is fantastic!  Not sure why it was messed up...

However, now I am stuck with another issue related to USB...  I do not recall having this issue with the original memstick .img file.  I will retry the installation with the original and see if I get the error...


----------



## fumanchu (Jul 30, 2021)

Okay, after further research in the forums and installing from the original memstick .img file, the message still happens... The boot does eventually succeeds... which is good.

Anyways, I believe this solutions finally works and I have a custom installation .img file!

Thank you so much for the wonder help... it is much appreciated!


----------



## fumanchu (Dec 6, 2021)

Okay, I am back...

I do have a custom .img being successfully created; however, I have now run into an issue when installing this .img to different hardware.  Also, we decided to use 12.2 instead of 13.

We have two models of computers we install the .img onto each having slightly different CPU and RAM, but the same SSD and HDD configuration. _ System 1_ has the SSD as ada0, while the HDD is ada1.  _System 2_ has the SSD as ada1, while the HDD is ada0.  This is causing major headaches since I have the _installerconfig _hardcoded to with


```
DISTRIBUTIONS="kernel.txz base.txz lib32.txz"
export ZFSBOOT_VDEV_TYPE=stripe
export ZFSBOOT_DISKS=ada0
export ZFSBOOT_SWAP_SIZE=2g
export nonInteractive="YES"
```

So to combat this, I commented out the _export nonInteractive="YES"_ statement.  This allowed the installer to prompt the user to pick the installation drive.  That all seemed to work as we were now able to pick the correct adaX; however, it does not seem to really work as the operating system is ALWAYS installed on ada0, I assuming because of the hardcoded _export ZFSBOOT_DISKS=ada0_.

So I thought, I will comment out the _export ZFSBOOT_DISKS=ada0_ statement, as that should take care of it... No dice, as I get an error when the installer tries to run...


```
No root partition was found. The root FreeBSD partition must have a mountpoint of '/'.
```

So, I am stuck.  Any idea on how to get the installer to allow for the user to pick the installation drive and not run into this error?

Thanks,


----------



## T-Daemon (Dec 7, 2021)

fumanchu said:


> export ZFSBOOT_DISKS=ada0


Remove `export nonInteractive="YES"`, set to

```
export ZFSBOOT_DISKS="ada0 ada1"
```

In the "ZFS Configuration" menu choose "stripe", "ada1".

I don't know how useful this is. If the installation is interactive now you might as well skip automatic installation setup and let the normal FreeBSD installer run.

Another option would be to create two installer images, specifying different disks, one for each model of computers.

Also be advised, the above installerconfig setup in this form won't install a  13.0-RELEASE bootable system on UEFI because of missing efi boot loader.

I assume there are or will be in the original installerconfig additional bsdinstall(8) targets like `rootpass` for example, and `time`.

The normal FreeBSD Installer would make much less trouble. Can't be a step by step installation guide, hard copy booklet or PDF, with images, to be used by the end client an option?



fumanchu said:


> Also, we decided to use 12.2 instead of 13.


12.2 will be EOL March 2022.








						FreeBSD Security Information
					

FreeBSD is an operating system used to power modern servers, desktops, and embedded platforms.




					www.freebsd.org
				




12.3-RELEASE + 3 months, 12.3-RELEASE available since December 2 2021.


----------



## fumanchu (Dec 7, 2021)

Thanks for the heads-up about 12.2...  We will go a head and update to 12.3...

You are 100% about not working with UEFI.  I am not quite sure what I am missing.  Here is my complete installerconfig file.


```
DISTRIBUTIONS="kernel.txz base.txz lib32.txz"
export ZFSBOOT_VDEV_TYPE="stripe"
export ZFSBOOT_DISKS="ada0"
export ZFSBOOT_SWAP_SIZE="2g"
export nonInteractive="YES"

#!/bin/sh

bsdconfig hostname
bsdconfig timezone
bsdconfig password

# For details see bsdconfig(8)

sysrc ifconfig_DEFAULT=DHCP
sysrc sshd_enable=YES

touch /firstboot
cp /usr/custom-dist/firstboot /etc/rc.d

# To make it aesthetically pleasant clear the screen
clear

printf  "#############################################################\n"
printf  "\n"
printf  "The custom FreeBSD has been installed.\n"
printf  "\n"
printf  "Please remove the installation media.\n"
printf  "\n"
printf  "Once the machine reboots, the firstboot process will\n"
printf  "automatically configure your installation.\n"
printf  "\n"
printf  "#############################################################\n"
printf  "\n"
printf  "Rebooting in...\n"
for i in $(/usr/bin/jot ${1:-10} ${1:-10} 1); do
    printf "\r%s " "$i"
    sleep 1
done

printf "\n"

reboot

# For details see  sysrc(8). For 'ifconfig_DEFAULT' see rc.conf(5).
```


----------



## T-Daemon (Dec 8, 2021)

T-Daemon said:


> Also be advised, the above installerconfig setup in this form won't install a 13.0-RELEASE bootable system on UEFI because of missing efi boot loader.





fumanchu said:


> You are 100% about not working with UEFI. I am not quite sure what I am missing. Here is my complete installerconfig file.


I apologize not to elaborate the issue and express myself clearer .

You are missing nothing. It's a bug in 13.0-RELEASE, affecting automatic installation of ZFS on UEFI.

As said before, bsdinstall(8) does not install the efi boot loader (in the right place).

In detail, loader.efi (or bootx64.efi, same loader, different name) is installed in a automatic installation in the new system under /boot/efi/efi/boot/bootx64.efi and /boot/efi/efi/freebsd/loader.efi.

/boot/efi/ on the other hand is a directory under / of dataset zroot/ROOT/default, on partition ada0p4, the freebsd-zfs partiton.

The place where the efi loader should be installed is on a FAT formatted, separate partition, ada0p1, mounted under /boot/efi, but that partition remains empty after the installation finishes.

And second, bsdinstall(8) doesn't create a EFI boot variable in UEFI to boot the system from.

The new system boots fine after creating appropriate directories and copy /boot/loader.efi to /boot/efi/boot/bootx64.efi, and creating a boot variable with efibootmgr(8).

This could be done as a workaround in the setup shell script part of /etc/installerconfig.

I'm not sure if it's the same bug discussed and reported below or a new one. I haven't tested 13.0-STABEL:

- Unattended install on FreeBSD13 with zfs/efi
- PR 255824 - Unattended install with UEFI and ZFS fails

It doesn't help to replace directory /usr/libexec/bsdinstall on 13.0-RELEASE installer media with the one from 13.0-STABLE. The installation terminates with a error message window popping up, the new system remains mounted, no UEFI boot variable is created, system doesn't reboot automatically.

Conclusion, automatic installation of 13.0-RELEASE is buggy at the moment. Maybe it's corrected in 13.1-RELEASE, depending on if it's the the same bug mentioned earlier.


----------



## fumanchu (Dec 9, 2021)

I now have UEFI working under 12.2 and 12.3.  I have not delved into 13 yet.

We have now moved onto 12.3 and we ran into another issue which I seem to not be able to solve.  But first a little background...

In the _.img_ I have created, are the packages (.pkg) I want to have installed.  Packages like tmux, tcpdump, sudo, etc., with all their dependencies.  I put them in the _.img_ because most of the time when doing an installation there is no Internet access...  Also in the_ .img_ is a _first_boot.sh_ script.  This script is put onto the new installation and automatically ran on first boot.  In this script I install the packages that were part of the _.img_ I created.  Herein lies the problem...

The problem is that since I am using pkg to install the various _.pkg_ files, I need to have the pkg software installed on the installation.  Seeing that pkg is already located in _/usr/sbin_, I though that I would simply perform


```
/usr/sbin/pkg add -f /installation/packages/pkg-1.17.2.pkg
```

and the problem would be solved... But no, I get a message saying:


```
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]:
```

As mentioned before, most of the time there is no Internet access so all the packages are in the_ .img_.  Is there a way to get around this?  Is there a way to use the built in _/usr/sbin/pkg_ command to install the pkg-1.17.2.pkg that I already have without having to go out to the Internet?  Hopefully this all makes sense...

Thanks,


----------



## T-Daemon (Dec 10, 2021)

fumanchu said:


> `/usr/sbin/pkg add -f /installation/packages/pkg-1.17.2.pkg`


No problem here form command line.


fumanchu said:


> As mentioned before, most of the time there is no Internet access so all the packages are in the_ .img_. Is there a way to get around this? Is there a way to use the built in _/usr/sbin/pkg_ command to install the pkg-1.17.2.pkg that I already have without having to go out to the Internet?


Yes it's possible. If you paste your firstboot.sh script it would be easier to suggest improvements, if necessary.

Below is a working example to bootstrap pkg and install extra packages on firstboot from a local repository (12.2-RELEASE):

/installation/packages directory topography:

```
/installation/packages/All/<packages>
/installation/packages/Latest/pkg.pkg  # renamed pkg-1.7.2.pkg
```

Download https://cgit.freebsd.org/ports/plain/sysutils/firstboot-pkgs/files/firstboot_pkgs.in

Apply patch to firstboot_pkgs:

```
--- firstboot_pkgs.orig    2021-12-10 08:29:54.818825000 +0200
+++ firstboot_pkgs    2021-12-10 08:33:28.616402000 +0200
@@ -2,7 +2,6 @@
 
 # KEYWORD: firstboot
 # PROVIDE: firstboot_pkgs
-# REQUIRE: NETWORKING
 # BEFORE: LOGIN
 
 # Add the following lines to /etc/rc.conf.local or /etc/rc.conf (in the disk
@@ -29,13 +28,16 @@
     # Count rc.d scripts
     nscriptso=`ls /usr/local/etc/rc.d | wc -l`
 
-    # Bootstrap and update pkg to ensure synchronization with the repository
+    # See pkg.conf(5) for variables
+    export PACKAGESITE=file:///installation/packages
+    export SIGNATURE_TYPE=none
+
+    # Bootstrap pkg
     env ASSUME_ALWAYS_YES=YES pkg bootstrap -f | cat
-    env ASSUME_ALWAYS_YES=YES pkg update -f | cat
 
-    # Install requested packages, if any
+    # Install requested packages, if any, from local repository
     for package in ${firstboot_pkgs_list}; do
-        env ASSUME_ALWAYS_YES=YES pkg install ${package} </dev/null |
+    env ASSUME_ALWAYS_YES=YES pkg add /installation/packages/All/${package}* </dev/null |
             cat
     done
```
 

```
mkdir -p /usr/local/etc/rc.d
cp firstboot_pkgs /usr/local/etc/rc.d
chmod 555 /usr/local/etc/rc.d/firstboot_pkgs

sysrc firstboot_pkgs_enable=YES
sysrc firstboot_pkgs_list="sudo tmux"

touch /firstboot
```


----------



## fumanchu (Dec 10, 2021)

Thanks for the update and information.  I will look into this today and provide feedback.


----------



## fumanchu (Dec 10, 2021)

Not sure if it matters or not, but we are now using 12.3-RELEASE, not 12.2-RELEASE...

Here is the information you asked for...

Our installerconfig automatically puts this script into _/etc/rc._d.


```
#!/bin/sh

# KEYWORD: firstboot
# PROVIDE: first_boot
# REQUIRE: NETWORKING
# BEFORE: login

. /etc/rc.subr

name="firstboot"
start_cmd="first_boot"
stop_cmd=":"

first_boot()
{
    /usr/custom-dist/first_boot.sh
}

load_rc_config $name
run_rc_command "$1"
```

Our installerconfig then does the following command to force a _firstboot _on the next reboot...


```
touch /firstboot
```

Then, on _firstboot_, our first_boot.sh script runs.


```
#!/bin/sh

# This script is run on first boot of the operating system.  After the first
# boot happens and the script is executed, the firstboot sentinel file located
# in /firstboot is automatically deleted by the operating system.  When this
# happens, the script is never run again.  If you need to rerun this script,
# create the firstboot sentinel file using the 'touch /furstboot' command to
# create the first boot sentinel file.  Once the file is created, reboot the
# system and this script will be run again.

#set -x

SIG_NONE=0
SIG_HUP=1
SIG_INT=2
SIG_QUIT=3
SIG_KILL=9
SIG_TERM=15

TIMEOUT=10

trap caught_signal $SIG_HUP $SIG_INT $SIG_QUIT $SIG_KILL $SIG_TERM

cleanup()
{
    if [ -e temp.txt ]; then
        rm -rf temp.txt
    fi

    # Restore the original configuration file.
    rm /etc/pkg/FreeBSD.conf
    mv /etc/pkg/FreeBSD.conf.ORIG /etc/pkg/FreeBSD.conf

    cd $_cwd

    exit 1
}

setup()
{
    _cwd=$PWD
    _pw=/usr/sbin/pw
    _shell=/bin/sh
    _uid="/usr/custom-dist"

    # Since we do not package signatures, we replace the original configuration
    # file with our configuration file so we do not need signatures.
    mv /etc/pkg/FreeBSD.conf /etc/pkg/FreeBSD.conf.ORIG
    cp $_uid/FreeBSD.conf /etc/pkg/FreeBSD.conf
}

caught_signal()
{
    logger "Caught Signal... Cleaning up."
    rmuser -y support
    cleanup
}

install_standard_packages()
{
    logger "Install standard packages..."

    # Install the package program.
    /usr/sbin/pkg add -f $_uid/packages/pkg-1.17.2.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "pkg has been installed successfully."
    fi
    
    # Install the Unix bash shell and command language.
    pkg add -f $_uid/packages/bash-5.1.8.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "bash has been installed successfully."
    fi
    
    # Install htop.  htop is an interactive system-monitor, process-viewer, and
    # process-manager.
    pkg add -f $_uid/packages/htop-3.0.5.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "htop has been installed successfully."
    fi
    
    # Install lnav.  lnav is an advanced log file viewer.
    pkg add -f $_uid/packages/lnav-0.9.0.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "lnav has been installed successfully."
    fi
    
    # Install 7zip.  7zip is an advanced file compression utility.
    pkg add -f $_uid/packages/p7zip-16.02_3.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "7zip has been installed successfully."
    fi
    
    # Install sudo. The sudo command allows users who are part of the wheel and
    # operator groups to run command as root with actually logging in as root.
    pkg add -f $_uid/packages/sudo-1.9.8p2.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "sudo has been installed successfully."
    fi
    
    # Install tcpdump.  tcpdump is a data-network packer analyer similar to Wire
    # Shark.
    pkg add -f $_uid/packages/tcpdump-4.99.0.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "tcpdump has been installed successfully."
    fi
    
    # Install tmux.  tmux is a terminal multiplexer for Unix-like operating
    # systems.  It allows multiple terminal sessions to be accessed simultaneously
    # in a single window. 
    pkg add -f $_uid/packages/tmux-3.2a.pkg
    result_code=$?
    if [ $result_code -eq 0 ]; then
        logger "tmux has been installed successfully."
    fi

    logger "Installing standard packages... Complete."
}

setup
install_standard_packages

echo ""
echo "**********************************************************************"
echo "Congratulations!"
echo "The final setup of the Custom FreeBSD installation is complete."
echo "**********************************************************************"
logger "Congratulations! The final setup of the Custom FreeBSD installation is complete."

cleanup

# shutdown -r now
```


----------



## T-Daemon (Dec 10, 2021)

fumanchu said:


> Not sure if it matters or not, but we are now using 12.3-RELEASE, not 12.2-RELEASE...


It doesn't matter.



fumanchu said:


> Our installerconfig automatically puts this script into _/etc/rc._d.


Base systems rc scripts shouldn't be mixed with custom rc script in /etc/rc.d/. All ports/packages install their scripts under /usr/local/etc/rc.d/ and custom scripts should go there also.



fumanchu said:


> # REQUIRE: NETWORKING


Why require NETWORKING when the installation of packages are offline from a local repository?


Tried out on a test system, your first_boot.sh works just fine, with some modifications.

Precondition is:

- a local package repository (/installation/packages)

The repository needs a topography pkg expects as shown below.

```
/installation/packages/All/<packages>
/installation/packages/Latest/pkg.pkg # renamed pkg-1.7.2.pkg
```
After all packages are in place, execute pkg-repo(8) on /installation/packages, which creates below files:

```
/installation/packages/{meta.conf, meta.pkg, meta.txz, packagesite.txz, packagesite.pkg}
```

- a package repository configuration file (i.e. local.conf)

I would put that file under /usr/local/etc/pkg/repos/ and disable /etc/pkg/FreeBSD.conf there and let it be removed after firstboot from fist_boot.sh, instead of moving/removing/copying the original and custom repository configuration files:

```
FreeBSD: { enabled: no }

local: {
    url: "file:///installation/packages"
    enabled: yes
}
```


In first_boot.sh set for all package installations global environment `ASSUME_ALWAYS_YES=yes`

With the repsitory configuration in effect, instead of

```
/usr/sbin/pkg add -f $_uid/packages/pkg-1.17.2.pkg
just
pkg bootstrap -f
```

and for all other packages, instead of

```
pkg add -f $_uid/packages/bash-5.1.8.pkg

pkg install bash
```


----------

