# Extending NanoBSD



## lucifercipher (Apr 12, 2014)

Gentlemen,

Hello. I followed the basic guide to test an image generation from https://www.freebsd.org/doc/en/articles/nanobsd/howto.html on FreeBSD 10 because I want to have my own embedded device that I can use at my office. It's the first time I am playing around with NanoBSD. Lets say I want to add Quagga, SNORT and few other packages and run on a computer with 2GB RAM and 6 NICs then what do I have to do? I want to use a CF IDE adapter for this purpose and have 8 GB cards lying around 
	

	
	
		
		

		
			





. 

I couldn't really find an easy explanation to adding packages and configuring them before image build. Any help will be appreciated.

Thanks.


----------



## trh411 (Apr 13, 2014)

Is 2.3.3. Adding packages what you are trying to do, or something else? Since you stated you used this reference to test image generation, I'm not sure if you missed the section on adding packages, or you are trying to do something else entirely.


----------



## lucifercipher (Apr 13, 2014)

Thanks for your reply. Yes I want to achieve something different like adding snort and preconfigure it before building the nanoBSD image. The reason I want to do this is to have save time and not going over the complete setups over and over again. Is this doable?  :i


----------



## junovitch@ (Apr 14, 2014)

Here is my config file that I use to build images for my Soekris router.

Some thoughts:
I use Puppet for configs, but I overlay all the configs at build time from my Puppet folder.  Puppet just handles maintaining configs after that.  

I install all my packages from my local web server.  If you are using public ones, you can remove the repo config part.  You may also want to copy the /var/cache/pkg from your build host to prevent it having to download packages over and over again.  You'll absolutely want to delete the package cache before the image gets made else you'll find your /var file system full as soon as you boot the image.

If you put this in /usr/src/tools/tools/nanobsd, you can build an image by doing this:
`cd /usr/src/tools/tools/nanobsd && sh nanobsd.sh -c soekrisconf.nano`

And if you already have an previous world/kernel around, you can skip that step with an extra flag.  This is what I've been doing to update to a full set of current packages.  Normally I will only update individual packages for security reasons because of the extra hassle of remounting read-write and making sure I remember to backup the package database and new files before remounting read-only.  Otherwise I just rebuild the whole image and reboot into the second partition.
`cd /usr/src/tools/tools/nanobsd && sh nanobsd.sh -c soekrisconf.nano -b`


```
NANO_NAME=soekris
NANO_KERNEL=SOEKRIS

# ada0: 15104MB (30932992 512 byte sectors: 16H 63S/T 16383C)
NANO_DRIVE=ada0
NANO_MEDIASIZE=30932992
# 32MB
NANO_RAM_ETCSIZE=65536
# 512MB
NANO_RAM_TMPVARSIZE=1042576
# 3 GB Data partition
NANO_CODESIZE=6291456
# Zero out second disk partition for better compression
NANO_INIT_IMG2=0
# 512 MB Reserve for CONF partition
NANO_CONFSIZE=1048576
# Remainder for Data rw mounted partition
NANO_DATASIZE=-1

CONF_WORLD='
BOOT_COMCONSOLE_SPEED=19200
WIHTOUT_BLUETOOTH=YES
WITHOUT_CALENDAR=YES
WITHOUT_FREEBSD_UPDATE=YES
WITHOUT_HTML=YES
WITHOUT_NTP=YES
WITHOUT_PORTSNAP=YES
WITHOUT_RCMDS=YES
WITHOUT_ROUTED=YES
WITHOUT_SENDMAIL=YES
WITHOUT_TELNET=YES
'

add_pkgs()
{
  # Put prep file/directories in place
  cp /etc/resolv.conf ${NANO_WORLDDIR}/etc/resolv.conf
  chroot ${NANO_WORLDDIR} sh -c \
    'mkdir -p /var/www; cd /usr/local && ln -s ../../var/www www'
  chroot ${NANO_WORLDDIR} sh -c \
    'ln -s /mnt/data/home /home'
  chroot ${NANO_WORLDDIR} sh -c \
    'mkdir -p /var/run/fail2ban'
  chroot ${NANO_WORLDDIR} sh -c \
    'mkdir -p /mnt/data; mkdir -p /mnt/usb; mkdir -p /mnt/tmp'

  # Make repo file
  mkdir -p ${NANO_WORLDDIR}/usr/local/etc/pkg/repos
  cat <<EOF > ${NANO_WORLDDIR}/usr/local/etc/pkg/repos/myrepo.conf
myrepo: {
  url: "http://pkg.home.lan/10_0amd64-default/",
  signature_type: 'none',
  enabled: yes,
}
FreeBSD: {
  enabled: no
}
EOF

  # Install packages
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} bootstrap
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install ports-mgmt/pkg
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install shells/bash
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/tmux
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/openntpd
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/openbgpd
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/puppet
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install security/openvpn
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/pstree
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net-mgmt/iftop
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/pftop
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install security/py-fail2ban
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/cmdwatch
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/tree
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/uptimed
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install editors/vim-lite
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install benchmarks/iperf
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/monitorix
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install sysutils/smartmontools
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/rsync
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/unison-nox11
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/isc-dhcp43-server
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/foreman-proxy
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install net/relayd
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install security/sudo
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install dns/ddclient
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install dns/bind99
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install ftp/tftp-hpa
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install ftp/vsftpd
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install www/squid33
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install www/nginx
  env ASSUME_ALWAYS_YES=YES pkg -c ${NANO_WORLDDIR} install mail/dma

  # Cleanup
  rm ${NANO_WORLDDIR}/etc/resolv.conf
  rm -r ${NANO_WORLDDIR}/var/cache/pkg
}

add_cfgs ()
{
  # Add persistent loader.conf tuning
  echo 'autoboot_delay="3"' >> ${NANO_WORLDDIR}/boot/loader.conf
  echo '# Delay boot to aid picking up drives' >> ${NANO_WORLDDIR}/boot/loader.conf
  echo 'kern.cam.boot_delay=10000' >> ${NANO_WORLDDIR}/boot/loader.conf

  # Add persistent sysctl.conf variables
  echo 'net.inet.ip.fastforwarding="1"' >> ${NANO_WORLDDIR}/etc/sysctl.conf
  echo 'net.inet.ip.random_id="1"' >> ${NANO_WORLDDIR}/etc/sysctl.conf

  # Add persistent mounts
  echo "/dev/${NANO_DRIVE}s4 /mnt/data ufs rw,failok 2 2" >> ${NANO_WORLDDIR}/etc/fstab

  # Enable openvpn to start before syslog/puppet/etc
  perl -pwi -e 's^# REQUIRE: DAEMON^# REQUIRE: NETWORKING\n# BEFORE:  SERVERS syslogd^g' \
    ${NANO_WORLDDIR}/usr/local/etc/rc.d/openvpn  

  # Add persistent symlinks to master OpenVPN rc.d script for multiple instances
  cd ${NANO_WORLDDIR}/usr/local/etc/rc.d \
    && ln -sv openvpn openvpn_server \
    && ln -sv openvpn openvpn_client

  # Make syslog settings persistent
  perl -pwi -e 's^#*.*\t\t\t\t\t\t\@loghost^*.*\t\t\t\t\t\t\@10.100.102.2^g' \
    ${NANO_WORLDDIR}/etc/syslog.conf  

  # Overlay the rest of the config from Puppet's manifest
  cd /usr/jails/puppet.home.lan/usr/local/etc/puppet/modules/soekris/files/common \
    && cp -Rfv * ${NANO_WORLDDIR}

  # Fix permissions on temp dir?
  chroot ${NANO_WORLDDIR} sh -c \
    'chmod 1777 /var/tmp'

  # Touch vsftpd log so fail2ban starts properly
  chroot ${NANO_WORLDDIR} sh -c \
    'touch /var/log/vsftpd.log'

  # Stage named security log directory
  chroot ${NANO_WORLDDIR} sh -c \
    'mkdir -p /var/log/named && chown bind:wheel /var/log/named && chmod 640 /var/log/named'
}

customize_cmd add_pkgs
customize_cmd add_cfgs
customize_cmd cust_comconsole
customize_cmd cust_install_files
```


----------



## lucifercipher (Apr 15, 2014)

Thank you for the detailed reply juno. Please clear my confusion a little. Lets say if i add snort via add_port "security/snort" and add snort_enable=YES to fire it up after every boot. But what will happem to SNORT config. Can i configure and pre-package it in the image so everytime it boots, it has my oinkmaster code and everything else? How do i go about setting up the configuration?

Thanks !


----------



## asteriskRoss (Apr 15, 2014)

Prepare the configuration files you want and put them in a directory of your choice.  Anything that would normally go in /etc should be placed in that directory.  Anything that would normally go in /usr/local/etc (likely to be what you need since you'll be configuring ports) should be placed in a subdirectory called "local".  In your NanoBSD configuration file set the "NANO_CFGDIR" variable to the directory path; something like:

```
NANO_CFGDIR=/usr/home/lucifercipher/nanobsd/conf
```

The contents of the specified directory will be copied to the configuration partition (often referred to as /cfg) of the NanoBSD image during creation.

On my (long) wish list is to find some time to write and submit an update to the official NanoBSD introduction to make it more of a step-by-step guide.  Your best option at the moment is often reading the /usr/src/tools/tools/nanobsd/nanobsd.sh script itself, which fortunately isn't very long and is quite easy to follow.


----------



## lucifercipher (Apr 15, 2014)

asteriskRoss, thank you sir!  I will try this and revert. I hope this works. Thanks for the detailed explanation and I get it now. Also thank you for the two important tips.


----------



## junovitch@ (Apr 15, 2014)

The only thing to keep in mind is the /cfg partition will only be in the _.disk.full file produced by the NanoBSD script.  If you do an in-place upgrade to the secondary code partition with the _.disk.image you won't get that /cfg partition with it.  You'll just have to try it out and find a strategy that works for you.  As I had mentioned, I overlay configs into the system at build time from my Puppet jail.  For example, the /etc/rc.conf at build time will be in /conf/base/etc/rc.conf.  If Puppet changes it, whenever I run `sh /root/save_cfg`, the newer version gets backed up to /cfg/rc.conf.  The old one from build time is still under /conf; it just gets overwritten at boot time with the one from /cfg.  So it's a bit confusing having all these copies of files around but once you get the hang of it it's not too bad.


----------



## asteriskRoss (Apr 16, 2014)

@junovitch makes an excellent point about upgrading in-place (by default NanoBSD includes two copies of the image on the media, so you can overwrite one with an upgraded version, test it and revert if necessary).  His script's add_cfgs() function writes the configuration into the NanoBSD image, rather than the configuration partition and certainly has the advantage of bundling configuration changes in with any upgrades you try out.  Using the configuration partition works better for me as it means I can build a single NanoBSD image (the _.disk.image file) and deploy it on multiple machines that have different configurations.  Since you're only looking at a single machine at the moment, it probably doesn't matter which method you choose.


----------

