Solved bsdinstall scripting guide/tutorial

After some thought and some tests: Don't involve bsdinstall.

Remove (rename) on the installer media /etc/rc.local, create custom rc.local, run the installer script from there:
Code:
sh   /root/bsdsysinstaller

sh:
#!/bin/sh

# example unattended installation script saved under /root/bsdsysinstaller

gpart create -s gpt ada0

# optional if system is BIOS
gpart add -t efi -a 4k -s 260m -l efiboot0 ada0

# optional if system is UEFI
gpart add -t freebsd-boot -s 512k -l boot0 ada0

gpart add -t freebsd-swap -a 1m -s 4g -l swap0 ada0
gpart add -t freebsd-ufs  -a 1m -s 20g -l ufs0 ada0
gpart add -t freebsd-ufs  -a 1m -l ufsdata0 ada0

# optional if BIOS
newfs_msdos -c1 -F32 /dev/ada0p1
mount_msdosfs  /dev/ada0p1  /mnt

mkdir -p /mnt/efi/freebsd
cp -a /boot/loader.efi /mnt/efi/freebsd

umount /mnt

# optional if UEFI
gpart bootcode -b /boot/pmbr  -p /boot/gptboot -i 2 ada0

# put geli configuration here
# geli attach provider

newfs -j  /dev/ada0p4.eli
newfs -j  /dev/ada0p5.eli

mkdir  /tmp/ufs
mount  /dev/ada0p4.eli   /tmp/ufs

tar xfC /usr/freebsd-dist/kernel.txz  /tmp/ufs
tar xfC /usr/freebsd-dist/base.txz    /tmp/ufs

cat <<EOF>> /tmp/ufs/boot/loader.conf
geom_eli_load="YES"
EOF

cat <<EOF>> /tmp/ufs/etc/fstab
/dev/ada0p3.eli        none    swap    sw    0    0
/dev/ada0p4.eli        /        ufs        rw    1    1
EOF

cat <<EOF>> /tmp/ufs/etc/rc.conf
hostname="example.org"
keymap="uk"
sshd_enable="YES"
ifconfig_DEFAULT="DHCP"
EOF

efibootmgr -c -a -L FreeBSD -l ada0p1:/efi/freebsd/loader.efi
 
After some thought and some tests: Don't involve bsdinstall.

Remove (rename) on the installer media /etc/rc.local, create custom rc.local, run the installer script from there:
Code:
sh   /root/bsdsysinstaller

sh:
#!/bin/sh

# example unattended installation script saved under /root/bsdsysinstaller

gpart create -s gpt ada0

# optional if system is BIOS
gpart add -t efi -a 4k -s 260m -l efiboot0 ada0

# optional if system is UEFI
gpart add -t freebsd-boot -s 512k -l boot0 ada0

gpart add -t freebsd-swap -a 1m -s 4g -l swap0 ada0
gpart add -t freebsd-ufs  -a 1m -s 20g -l ufs0 ada0
gpart add -t freebsd-ufs  -a 1m -l ufsdata0 ada0

# optional if BIOS
newfs_msdos -c1 -F32 /dev/ada0p1
mount_msdosfs  /dev/ada0p1  /mnt

mkdir -p /mnt/efi/freebsd
cp -a /boot/loader.efi /mnt/efi/freebsd

umount /mnt

# optional if UEFI
gpart bootcode -b /boot/pmbr  -p /boot/gptboot -i 2 ada0

# put geli configuration here
# geli attach provider

newfs -j  /dev/ada0p4.eli
newfs -j  /dev/ada0p5.eli

mkdir  /tmp/ufs
mount  /dev/ada0p4.eli   /tmp/ufs

tar xfC /usr/freebsd-dist/kernel.txz  /tmp/ufs
tar xfC /usr/freebsd-dist/base.txz    /tmp/ufs

cat <<EOF>> /tmp/ufs/boot/loader.conf
geom_eli_load="YES"
EOF

cat <<EOF>> /tmp/ufs/etc/fstab
/dev/ada0p3.eli        none    swap    sw    0    0
/dev/ada0p4.eli        /        ufs        rw    1    1
EOF

cat <<EOF>> /tmp/ufs/etc/rc.conf
hostname="example.org"
keymap="uk"
sshd_enable="YES"
ifconfig_DEFAULT="DHCP"
EOF

efibootmgr -c -a -L FreeBSD -l ada0p1:/efi/freebsd/loader.efi
Thanks.

Is that really sufficient? Is tar xvf all there is to it? My script has already generated the correct fstab file for use under /tmp/bsdinstall_etc/fstab, etc. Now, I have multiple GELI containers (each of the partitions is a container). How do I unlock them at boot with a single passphrase from the user?

Returning to my incredulity above, the reason I am dubious is that BSD / Slackware are KISS type of OS'es in terms of philosophy. So, I find it difficult to believe that someone went through the trouble of writing a GUI (ncurses?) based installer when it is really that simple under the hood.
 
Is that really sufficient? Is tar xvf all there is to it?
Yes, extracting kernel.txz and base.txz packages (distribution sets) is all it takes to install the system. The rest is system configuration, and third party application installation.

My script has already generated the correct fstab file for use under /tmp/bsdinstall_etc/fstab, etc
Note that the bsdinstall_* configuration files will not be read if bsdinstall is not used in this custom scripted installation.

Now, I have multiple GELI containers (each of the partitions is a container). How do I unlock them at boot with a single passphrase from the user?
I assume the system Root-on-UFS will be installed in one of the geli providers (container), then use the "geli init -g" option for all providers.
Code:
                -g                Enable booting from this encrypted root
                                  filesystem.  The boot loader prompts for the
                                  passphrase and loads loader(8) from the
                                  encrypted partition.
But then the installation script will not be unattended, it will be interrupted, a passphrase and a confirmation of the passphrase will be requested during initialization and “geli attach”.

Example:
Code:
geli  init -g  -l  256  -s 4096  ada0p4  ada0p5
When the machine is restarted after the installation has finished, the passphrase is prompted directly before the FreeBSD boot menu. All providers are unlocked by entering the passphrase once.

Returning to my incredulity above, the reason I am dubious is that BSD / Slackware are KISS type of OS'es in terms of philosophy. So, I find it difficult to believe that someone went through the trouble of writing a GUI (ncurses?) based installer when it is really that simple under the hood.
The menu guided installation makes it easy for all kind of users to install the system, whether they are absolute beginners or experts.

The goal of the FreeBSD Foundations is to reach a large audience. It would not help the cause to offer only a manual installation method, as this would discourage less experienced newcomers to FreeBSD. But a FreeBSD beginner can install and configure the system in a few minutes without any prior knowledge by simply booting the installation media and following the instructions.
 
Yes, extracting kernel.txz and base.txz packages (distribution sets) is all it takes to install the system. The rest is system configuration, and third party application installation.


Note that the bsdinstall_* configuration files will not be read if bsdinstall is not used in this custom scripted installation.


I assume the system Root-on-UFS will be installed in one of the geli providers (container), then use the "geli init -g" option for all providers.
Code:
                -g                Enable booting from this encrypted root
                                  filesystem.  The boot loader prompts for the
                                  passphrase and loads loader(8) from the
                                  encrypted partition.
But then the installation script will not be unattended, it will be interrupted, a passphrase and a confirmation of the passphrase will be requested during initialization and “geli attach”.

Example:
Code:
geli  init -g  -l  256  -s 4096  ada0p4  ada0p5
When the machine is restarted after the installation has finished, the passphrase is prompted directly before the FreeBSD boot menu. All providers are unlocked by entering the passphrase once.


The menu guided installation makes it easy for all kind of users to install the system, whether they are absolute beginners or experts.

The goal of the FreeBSD Foundations is to reach a large audience. It would not help the cause to offer only a manual installation method, as this would discourage less experienced newcomers to FreeBSD. But a FreeBSD beginner can install and configure the system in a few minutes without any prior knowledge by simply booting the installation media and following the instructions.
Thanks. I find this method to be much more simplified and amenable to a scripted install. How do I create a user in this script? adduser in chroot (how?)? Or do I edit /etc/passwd and /etc/group directly, after creating /home/${USER}. I have some useful profile files already created under /etc/skel, so I assume I need to use adduser/useradd?
 
How do I create a user in this script? adduser in chroot (how?)? Or do I edit /etc/passwd and /etc/group directly, after creating /home/${USER}. I have some useful profile files already created under /etc/skel, so I assume I need to use adduser/useradd?
If you mean by profile files like -f file in adduser(8) to install in batch mode without user interaction
Code:
     -f file
             Get the list of accounts to create from file.  If file is “-”,
             then get the list from standard input.  If this option is
             specified, adduser will operate in batch mode and will not seek
             any user input.  If an error is encountered while processing an
             account, it will write a message to standard error and move to
             the next account.  The format of the input file is described
             below.
then it's possible. Assuming /etc/skel/<profile_files> is on the new installed system and /mnt the mount point of it:
Code:
chroot   /mnt  adduser -f /etc/skel/profile1
chroot   /mnt  adduser -f /etc/skel/profile2
file format being like
Code:
john:::::::::<clear_text_user_password>
jane::::::::/bin/tcsh:<clear_text_user_password>
Code:
FORMAT
     When the -f option is used, the account information must be stored in a
     specific format.  All empty lines or lines beginning with a ‘#’ will be
     ignored.  All other lines must contain ten colon (‘:’) separated fields
     as described below.  Command line options do not take precedence over
     values in the fields.  Only the password field may contain a ‘:’
     character as part of the string.

           name:uid:gid:class:change:expire:gecos:home_dir:shell:password

If you need finer-grained user creation options, use pw(8) instead
Code:
chroot  /mnt  pw  useradd  -n john  -m  -w  yes
chroot  /mnt  pw  useradd  -n jane  -m  -M 700  -G wheel,operator -L staff -s /bin/tcsh  -H <encrypted_password_string_file>
-n name login name
-m [ -k dir ] create and set up home
-w method set default password method
-M mode home directory permissions
-G grp1,grp2 additional groups
-L class user class (requires existing user login class in /etc/login.conf)
-s shell name of login shell
-H fd read encrypted password on fd

For more options and detailed description, see USER OPTIONS in pw(8).

Edit: However, adduser(8) has the advantage on ZFS, if a dataset is wanted for every user, this is created automatically, with pw(8) it is not.
 
Last edited:
Thanks.

If I want to use a shell script variable inside chroot, are there any special considerations to keep in mind? Does the shell interpreter take all within the quotes in chroot block literally, or does it substitute the values of variables?
 
If I want to use a shell script variable inside chroot, are there any special considerations to keep in mind? Does the shell interpreter take all within the quotes in chroot block literally, or does it substitute the values of variables?
There shouldn't be any problems. Anyway, a test run should show if the variables in the shell script are applied as expected. The test can be performed from the installation media in a VM.
 
Back
Top