HOWTO create secured ESXi enterprise image with GELI and pf

After using FreeBSD irregularly for almost 10 years, I've started using it quite a bit more recently. Over the past couple of days I've put together a FreeBSD 9.1 amd64 image I'll be using for various tasks on VMWare ESXi.

The image should satisfy the usual requirements of an enterprise: SNMP, remote syslog-ing, NTP, VMWare Tools, UTF-8 character set, etc. If you see anything crucial I forgot, please comment below.

While trying to be as generic as possible for many possible use cases, the main goal of the setup, however, is security. Thus,
  • the image is fully encrypted using geli() (except the bootloader) and requests one single passphrase at boot, the /var/log partition is separate and, of course, encrypted,
  • the pf() firewall is set to block log all by default for incoming and outgoing connections,
  • even with firewall turned off, the only two open ports are TCP/22 and UPD/161 for authenticated SNMPv3 users. (This is quite different from the default installation of some services that listen, often under root, on TCP/25 (sendmail), UDP/514 (syslogd), UDP/123 (ntpd).) sshd is the single service listening on network under the root account.
  • When the installation is finished, the system is fully up-to-date and ready to be updated using the standard tools: freebsd-update(), portmaster(8).

There are two reasons I'm putting this together
  • I've spent quite a bit of time creating the image and came across several non-trivial situations. I might soon forget how I solved them and/or in what exact order. FreeBSD Forums post allows me to document everything (with a very nice formatting) for future reference to me and to anyone that might find it useful.
  • I'm hoping that the readers will suggest improvements, correct errors and help the image get better over time. I'd appreciate your feedback!

I try to give credit where it's due. If I forgot to mention somebody's work, please let me know.

Without further ado, let's get our hands dirty.

Basic installation
Credit: http://namor.userpage.fu-berlin.de/howto_fbsd9_encrypted_ufs.html

During the installation we deselect all distribution sets and when asked about partitioning we select "Shell". This is what we are trying to achieve

Code:
# gpart show -l
=>      34  41942973  da0  GPT  (20G)
        34         6       - free -  (3.0k)
        40       128    1  (null)  (64k)
       168   1048576    2  boot  (512M)
   1048744   2097152    3  swap  (1.0G)
   3145896   3145728    4  varlog  (1.5G)
   6291624  35651376    5  root  (17G)
  41943000         7       - free -  (3.5k)

# cat /etc/fstab
/dev/gpt/boot   /mnt/boot_unencrypted   ufs     rw,noatime      1       1
/dev/gpt/swap.eli       none    swap    sw      0       0
/dev/da0p5.eli       /       ufs     rw,noatime      1       1
/dev/gpt/varlog.eli     /var/log        ufs     rw,noatime      1       1

and this is how we do it
Code:
#CREATE BOOT BLOCK
gpart destroy -F da0      #it is OK to receive an error here, if drive is new
gpart create -s gpt da0

gpart add -t freebsd-boot -s 64k -a 4k da0
gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 da0

#CREATE AND FORMAT BOOT PARTITION
gpart add -t freebsd-ufs -s 512m -a 4k -l boot da0
newfs -U gpt/boot

#CREATE PARTITION FOR ENCRYPTED SWAP
gpart add -t freebsd-swap -s 1g -a 4k -l swap da0

#CREATE PARTITIONS FOR ENCRYPTED NONROOT FILESYSTEMS
gpart add -t freebsd-ufs -s 1536m -a 4k -l varlog da0

#CREATE AND INIT ENCRYPTED ROOT VOLUME
gpart add -t freebsd-ufs -a 4k -l root da0
geli init -b -l 256 -e AES-XTS gpt/root
# insert complex passphrase, [color="Red"]if it is lost, all setup is lost[/color]
geli attach gpt/root

#FORMAT ENCRYPTED ROOT VOLUME
newfs -U gpt/root.eli

#MOUNT ROOT AND BOOT FILESYSTEMS
mount /dev/gpt/root.eli /mnt
mkdir -p /mnt/mnt/boot_unencrypted
mount /dev/gpt/boot /mnt/mnt/boot_unencrypted
cd /mnt
ln -s boot_unencrypted boot
cd ..

#PREPARE KEYS FOR NONROOT PARTITIONS
mkdir -p /mnt/root/geli_keys
chmod 0400 /mnt/root/geli_keys
head -c 32 /dev/random > /mnt/root/geli_keys/varlog.key

#INIT ENCRYPTED NONROOT PARTITIONS
geli init -P -l 256 -K /mnt/root/geli_keys/varlog.key gpt/varlog
geli attach -p -k /mnt/root/geli_keys/varlog.key gpt/varlog

#FORMAT ENCRYPTED NONROOT VOLUMES
newfs -U gpt/varlog.eli

#MOUNT ENCRYPTED NONROOT VOLUMES
mkdir -p /mnt/var/log
mount /dev/gpt/varlog.eli /mnt/var/log

#CONTINUE INSTALLATION

#POST INSTALLATION
Choose "Shell" when installation finished for "final modifications"

#CONFIG BOOT LOADER
echo >> /boot/loader.conf << __EOF__
aesni_load="YES"
geom_eli_load="YES"
vfs.root.mountfrom="ufs:/dev/da0p5.eli"
__EOF__

#CONFIG FSTAB
echo >> /etc/fstab << __EOF__
/dev/gpt/boot    /mnt/boot_unencrypted   ufs    rw,noatime    1    1
/dev/gpt/swap.eli    none   swap    sw    0    0
/dev/da0p5.eli /        ufs    rw,noatime    1    1
/dev/gpt/varlog.eli /var/log        ufs    rw,noatime    1    1
__EOF__

#MAKE SWAP ENCRYPTED
echo >> /etc/rc.conf << __EOF__
geli_swap_flags="-e AES-XTS -l 256 -s 4096 -d"
__EOF__

#MAKE SURE ENCRYPTED NONROOT PARTITIONS ARE AUTOATTACHED
echo >> /etc/rc.conf << __EOF__
geli_gpt_varlog_flags="-p -k /root/geli_keys/varlog.key"
__EOF__

Notes:
  • For some reason, /dev/da0p5 can not be specified as gpt/boot in /boot/loader.conf nor in /etc/fstab. It seems there's some trouble with the order of the start up scripts.
  • swap is encrypted using a random password.
  • Hardware acceleration of AES is enabled using the kernel module aesni. It should fail safe even if the CPU doesn't support it.
  • The flag "-a 4k" for the gpart add command makes sure the partitions are alligned for 4kB disks. It doesn't hurt even if we don't have them, since 512B * 8 = 4kB :).
  • We are not setting up any kind of redundancy at this level (e.g. gmirror(), nor zfs()). We're setting the template for the enterprise ESX environment where the virtual harddrives (vmdks) are placed on the datastores on top of highly reliable RAID arrays.
  • Also, we're not setting up any kind of backups. We're trying the set everything in such way, that an accidental power failure won't be a problem. Thus, backing up raw VMWare vmkd while the machine is running shouldn't be a problem either. From the security point of view, it is no problem an "untrusted" backup solutions handle our disk image since it is encrypted (except the bootloader) with the complex passphrase known only to us.

Shortcomings and residual risk:
  • We're silently assuming nobody messes up our unencrypted bootloader and make us enter the passphrase to such untrusted environment.
  • We are again silently assuming the path "from our fingers to the bootloader" is secure. That is, we're assuming there are no emanation receptors :h, hardware keyloggers, software keyloggers, SSL connections broken into, malicious administrators of the ESX hypervisors, etc.
  • Well, we are silently assuming many things :).
  • We could place the bootloader on a thumbdrive and insert it with every boot (again silently assuming noone will overwrite it from the inside before booting). Also, we would have to remember to mount the thumbdrive everytime we run # freebsd-update install which is not that ofen so we'd probably forget.
  • Ultimately, the "security" is always a trade off. Also, the name of the post doesn't promise a "secure installation" but a "secured installation" :).
 
UTF-8 Character set
Credit: http://www.b1c1l1.com/blog/2011/05/09/using-utf-8-unicode-on-freebsd/
Add the blue text to /etc/login.conf
Code:
       :setenv=MAIL=/var/mail/$,BLOCKSIZE=K[color="Blue"],LC_COLLATE=C[/color]:\
       [color="Blue"]:charset=UTF-8:\
       :lang=en_US.UTF-8:[/color]
and apply changes by # cap_mkdb /etc/login.conf.

make.conf configuration
We'll use the following content of /etc/make.conf. Feel free to comment.
Code:
CPUTYPE?=[color="Blue"]xxx[/color] # choose as needed
WITH_PKGNG=yes
WITHOUT_DEBUG=YES
NO_NIS=YES
WITH_NEW_XORG=true

Bringing FreeBSD up to date
Before installing any ports, we want to make sure we're fresh.
Code:
freebsd-update fetch
freebsd-update install

3rd party applications from ports
We'll only be using /usr/ports system and portmaster(8) for 3rd party applications. (The single exception will be the VMWare tools which might be requested by whoever owns the ESX environment.)
Code:
portsnap fetch
portsnap extract # only with first run
portsnap update # all consecutive runs

cd /usr/ports/ports-mgmt/portmaster && make && make install clean
portmaster ports-mgmt/portaudit
portaudit -F
Notes:
  • We'll make sure we consult /usr/ports/UPDATING between every run of # porsnap fetch update and # portmaster -a in the future.
  • We've just installed and updated portaudit(). It won't allow us to install ports with known vulnerabilities. We should keep it up-to-date by running # portaudit -F regularly.

Sending logs to remote location via net/syslog-ng
We will not use the default syslog() daemon since it insists on listening on network (port UDP/514) under the root account. Also, it doesn't support reliable remote logging using via the port TCP/601. Thus, we'll use net/syslog-ng.
Code:
portmaster sysutils/syslog-ng # SSL from system

# syslog-ng promises this is as close to default as possible
cp /usr/local/etc/syslog-ng.conf.sample /usr/local/etc/syslog-ng.conf

# maybe a little to close (this will make syslog-ng NOT listen on network)
vi /usr/local/etc/syslog-ng.conf
# remove "udp()" from source src{ ... }

cat >> /usr/local/etc/syslog-ng.conf << __EOF__
filter f_bigbrother     { not level(debug); };
destination d_bigbrother { tcp("192.168.60.1" port(601)
                              log_fifo_size(16777216)
                              flags(no_multi_line)
                              throttle(20)); };
log                     { source(src); filter(f_bigbrother); destination(d_bigbrother); };
__EOF__

cat >> /etc/rc.conf  << __EOF__
syslogd_enable="NO"
syslog_ng_enable="YES"
__EOF__

service syslogd stop
service syslog-ng start

sendmail() "configuraton"
We will not be using sendmail. We'll be using syslog and SNMP for monitoring.
Code:
cat >> /etc/rc.conf << __EOF__
sendmail_enable="NONE"  # setting "NO" is not enough
__EOF__

service sendmail onestop

Time synchronization
The default ntpd(8) insists on listening on network on port UDP/123. We'll use net/openntpd which is secure and sufficient.
Code:
portmaster net/openntpd

cat >> /usr/local/etc/ntpd.conf << __EOF__
# ntp-dc1.company.local
server 192.168.2.123
# ntp-dc2.company.local
server 192.168.202.123
__EOF__

cat >> /usr/local/etc/syslog-ng.conf << __EOF__
filter f_ntp           { facility(ntp); };
destination d_ntp { file("/var/log/ntp.log"); };
log                     { source(src); filter(f_ntp); destination(d_ntp); };
__EOF__

service syslog-ng reload

cat >> /etc/rc.conf << __EOF__
openntpd_enable="YES"
__EOF__
Notes:
  • ntpd(8) sends its logs by default to the local syslog which we already configured to send everything (besides debug) to the remote location. Here, we also instructed syslog-ng(8) to send these logs to the local file /var/log/ntp.log.
  • Time synchronizaton is crucial for many things also besides security. Making sure it works by monitoring its logs should not be forgotten.

Configure authenticated SNMPv3 access
We don't want no "community strings". We want authenticated users. Thus, we use SNMPv3 in net-mgmt/net-snmp.
Code:
portmaster net-mgmt/net-snmp

pw groupadd -n snmpd
pw useradd -d /nonexistent -c "SNMP daemon user" -s /usr/sbin/nologin -n snmpd

net-snmp-config --create-snmpv3-user \
                -ro -a SHA -A SUPERSECRETPASSWORD -x DES  snmpv3monitor

cat >> /etc/rc.conf << __EOF__
snmpd_enable="YES"
snmpd_flags="-r -a -u snmpd -g snmpd -Lf /dev/null"
snmpd_conffile="/usr/local/share/snmp/snmpd.conf"
__EOF__

Remarks:
  • We're not setting encryption password here, as the as the monitoring system at author's work didn't support it, it wouldn't be tested.
  • snmpd(8) is not running under the root account (as opposed to the default settings).
  • The flag "-r" is important as it tells snmpd to give up if an access is denied. This can be confirmed during a full SNMP walk, when the daemon crashes. The reason is that the non-root account doesn't have access to /dev/kmem. ??/dev/kmem !! That definitely doesn't seem right.
  • The flag "-Lf /dev/null" is also important. Without it, the /var/log partition gets filled pretty quickly if the monitoring system is monitoring us on minute basis with several sensors. If we do need the logs of snmpd(8), we send them to syslog as we do later on with the firewall logs.

Security concerns
  • We skipped the authorization step completely by giving the SNMP user snmpv3monitor access to all OIDs provided by SNMP. If this is a concern, we adjust the # net-snmp-config statement as needed.
Installation of VMWare Tools
Credit: http://www.rhyous.com/2012/05/09/installing-vmware-tools-on-freebsd-9-without-xorg/
We use the official tools from VMWare. We have to update the source and have ESX insert the additions image to the CD drive of the virtual machine.
Code:
portmaster misc/compat6x

portmaster devel/subversion
vi ~/.subversion/servers
svn co http://svn.freebsd.org/base/releng/$(uname -r | cut -d "-" -f 1) /usr/src
rm -rf ~/.subversion/servers

mkdir /cdrom
mount -t cd9660 /dev/cd0 /cdrom
cp /cdrom/vmware-freebsd-tools.tar.gz /root
umount /cdrom/

cd /root
tar -xzf vmware-freebsd-tools.tar.gz

cd /root/vmware-tools-distrib/lib/modules/source/
tar -xf vmmemctl.tar
cd vmmemctl-only
make
make install

cd /root/vmware-tools-distrib/lib/modules/source/
tar -xf vmblock.tar
cd vmblock-only
make
make install

cd /root/vmware-tools-distrib/
./vmware-install.pl

# clean up
rm -rf /root/vmware-tools-distrib/
rm -f /root/vmware-freebsd-tools.tar.gz
rm -rf /usr/src/*
Notes
  • If we are behind a HTTP proxy, updateing with svn(8) can be tricky. Credit: The steps above work from behind a HTTP proxy if you set ii in ~/.subversion/servers thanks to http://forums.freebsd.org/showpost.php?p=197584&postcount=4 .
  • As an alternative to the official VMWare Tools for FreeBSD, there is unnoficial emulators/open-vm-tools-nox11.
  • Upsides:
    • We can update them (and not forget) during the standard # portmaster -a process.
    • There is no need to play with the virtual CD images in VMWare console.
    • There is no need to manually # make install clean anything. We still need the up-to-date system sources in /usr/src, however.
    • Integration with FreeBSD rc.d start up scripts and the service() command. The official version just starts with no hint on what is going n.
  • Downsides:
    • Your management and/or the ESX owner might not like the gray (instead of green) status icon in VMWare management console saying "3rd party unmanaged" (instead of "Up to date"). This might be seen as an SLA issue with VMWare.

Security concerns
  • We've just installed a backdoor running under root on our system. If this is a concern, we deinstall.
  • VMWare Tools, no matter if official or from ports, allow the ESX administrator to do many things to our system. On the other hand, they allow us to benefit from the ESX features such as live migration, IP address display in VMWare console, no trouble with the SLA, etc. Again, the security is a tradeoff.
  • What we could do is to disable the tools when not necessary. The benefits would be questionable, the impact could be disastrous.

Configuration of sudo
We don't want to be digging out the passphrase for the root user from a security/keepassx database everytime we want to run, e.g. tcpdump(1). We definitely won't be telling the passphrase to any other users of the system even if we'd want them to have root access. (Anonymous root access is "No good."(c)) Thus, we install security/sudo.

Code:
portmaster security/sudo

visudo

%wheel ALL=(ALL) NOPASSWD: ALL
Notes
  • We allowed the members of the wheel group to switch to root by [CMD=]sudo su -[/CMD] without entering any kind of password. Such users must log in to the system using their SSH key, and must have a complex user passphrase for a terminal access (if such access is needed).
 
pf() firewall configuraton
Load the kernel modules manually and automatically after boot
Code:
kldload pf
kldload pflog

cat >> /boot/loader.conf << __EOF__
pf_load="YES"
pflog_load="YES"
__EOF__

We set up /usr/local/etc/pf-marwis.conf so it takes into account all of the services we've configured so far and nothing else. By default, we block all incoming and outgoing traffic. The following setup for instance doesn't allow to telnet to any server on port TCP/80 (reads as "opening reverse shell"), besides the update server.

Credit: http://www.thedeepsky.com/howto/newbie_pf_guide.php (it seems to be offline at the moment, here's the Internet Archive copy)
Code:
## marwis on forums.freebsd.org: restrictive bidirectional firewall configuration
## marwis@gmail.com, Martin Hlavac, March 31, 2013
## based on http://www.thedeepsky.com/howto/newbie_pf_guide.php

##############
### Macros ###
##############
SYN_ONLY="S/FSRA"
EXT_NIC="em0"
LOOPBACK_NIC="lo0"

# IP address on $EXT_NIC interface
EXT_IP="192.168.2.2"

# default ports
SSH_PORT="22"

# allowed ICMP types
ALLOWED_ICMP="{ echoreq, unreach }"

# Monitoring via SNMP (UDP) and ICMP probes
SNMPMON_IP="192.168.2.161"
SNMPMON_UDP_PORT="161"

# NTP Time Synchronization (UDP)
NTP_IP="{ 192.168.2.123, 192.168.202.123 }"
NTP_UDP_PORT="123"

# Remote syslog logging (TCP)
SYSLOG_IP="192.168.60.1"
SYSLOG_PORT="601"

# Domain name servers (UDP)
DNS_IP="{ 192.168.2.53, 192.168.2.153 }"
DNS_PORT="53"

# Update Server (TCP)
UPDATES_IP="192.168.31.28"
UPDATES_PORT="3128"

##############
### TABLES ###
##############
# we're not usint tables so far, just in case, this is the syntax
#table <block_hosts> persist
#table <private> const { 10/8, 172.16/12, 192.168/16, 224/8 }
# Global filter stuff
#block in log quick on $EXT_NIC from <block_hosts> to any
#block in log quick on $EXT_NIC from <private> to any

######################
### GLOBAL OPTIONS ###
######################
set loginterface $EXT_NIC
set block-policy return

## TRAFFIC NORMALIZATION
scrub in on $EXT_NIC all fragment reassemble
scrub out on $EXT_NIC all fragment reassemble random-id no-df

# Block spoofed packets
antispoof log quick for $EXT_NIC

######################
### QUEUEING RULES ###
######################
# we're not using queuing

##############################
## TRANSLATION RULES (NAT) ###
##############################
# we're on a single-interface workstation, no NAT is needed/possible

####################
### FILTER RULES ###
####################
# Block everything (inbound AND outbound on ALL interfaces) by default (catch-all)
block log all
# Block IPv6 (explicitely allow IPv4, inet, when needed)
block log inet6 all

# Pass everything on localhost
pass on $LOOPBACK_NIC all no state

# Default TCP policy - incoming and sessions
block return-rst in log on $EXT_NIC inet  proto tcp all
   # allow SSH from anywhere
   pass in quick on $EXT_NIC inet proto tcp from any to $EXT_IP port $SSH_PORT flags $SYN_ONLY modulate state

# Default TCP policy - outgoing
block return-rst out log on $EXT_NIC inet proto tcp all
   # Remote syslog
   pass out quick on $EXT_NIC inet proto tcp from $EXT_IP to $SYSLOG_IP port $SYSLOG_PORT modulate state
   # Domain name service
   pass out quick on $EXT_NIC inet proto tcp from $EXT_IP to $DNS_IP port $DNS_PORT modulate state
   # Update server
   pass out quick on $EXT_NIC inet proto tcp from $EXT_IP to $UPDATES_IP port $UPDATES_PORT modulate state

# Default UDP policy - incoming and "sessions"
block in log on $EXT_NIC inet proto udp all
   # Monitoring sensor in and out
   pass in quick on $EXT_NIC inet proto udp from $SNMPMON_IP to $EXT_IP port $SNMPMON_UDP_PORT keep state
   # Time synchronization
   pass in quick on $EXT_NIC inet proto udp from $NTP_IP to $EXT_IP port $NTP_UDP_PORT keep state

# Default UDP policy - outgoing
block out log on $EXT_NIC proto udp all
   # Domain Name Service
   pass out quick on $EXT_NIC inet proto udp from $EXT_IP to $DNS_IP port $DNS_PORT keep state
   # Time synchronization
   pass out quick on $EXT_NIC inet proto udp from $EXT_IP to $NTP_IP port $NTP_UDP_PORT keep state

# Default ICMP policy - incoming
block in log on $EXT_NIC inet proto icmp all
   pass in quick on $EXT_NIC inet proto icmp from any to $EXT_IP icmp-type $ALLOWED_ICMP keep state
   # Monigoring Ping probes (just in case default ICMP policy would block it)
   pass in quick on $EXT_NIC inet proto icmp from $SNMPMON_IP to $EXT_IP icmp-type $ALLOWED_ICMP keep state

# Default ICMP policy - outgoing
block out log on $EXT_NIC inet proto icmp all
   # allow ICMP types required to work by RFC
   pass out quick on $EXT_NIC inet proto icmp from $EXT_IP to any icmp-type $ALLOWED_ICMP keep state

Notes
  • Even though the synproxy option is usualy mentioned in multi-interface scenarios, we could try to use it for the SSH traffic on the port TCP/22. We would fail, however, as Putty running on Windows 7 machine wouldn't connect. Option modulate seems to work fine.
  • IPv6 is disabled completely by block log inet6 all. All of the allowed traffic explicitely specifies IPv4, i.e. inet.
  • If we want allow IPv6 in the future, all of the rules (especially the block rules) will have to be adjusted, e.g. by removing inet.

Set the automatic start of the firewall after boot and for now, start it manually
Code:
cat >> /etc/rc.conf << __EOF__
pf_enable="YES"
pf_rules="/usr/local/etc/pf-marwis.conf"
pf_flags=""
pflog_enable="YES"
pflog_logfile="/var/log/pflog"
pflog_flags=""
__EOF__

service pflog start
service pf start

Sending firewall logs to remote syslog
Our paranoid security department tells us they want to see the logs with all connections dropped by the packet filter. It's good thing we've already set up sysutils/syslog-ng to send local syslog logs to a remote location. Thus, it is sufficient to redirect the logs of pf() to local syslog. We make use of sysutils/daemontools to make it simple, reliable and realtime.

Code:
portmaster sysutils/daemontools
mkdir -p /service

cat >> /etc/rc.conf << __EOF__
svscan_enable="YES"
svscan_servicedir="/service"
__EOF__

service svscan start

Creating and adding scripts is very easy, while supervise(8) from sysutils/daemontools is rock solid. (It's the default watchdog for qmail(7), tinydns(8) and other software written by Daniel Bernstein (djb).)

Code:
mkdir -p /var/service/pf2syslog/log

cat >> /var/service/pf2syslog/run << __EOF__
#!/bin/sh
exec 2> /dev/null
exec /usr/sbin/tcpdump -nn -e -l -tttt -i pflog0 -s 0
__EOF__
chmod +x /var/service/pf2syslog/run

cat >> /var/service/pf2syslog/log/run << __EOF__
#!/bin/sh
exec /usr/bin/logger -p local0.notice -i -t pf2syslog
__EOF__
chmod +x /var/service/pf2syslog/log/run

ln -s /var/service/pf2syslog /service/

When digging through firewall logs "on the remote location" in the future, it may not be evident what the firewall configuration used to be (e.g. rules numbers, etc.). Thus, we periodically send the verbose firewall configuration to syslog, as well.

Code:
mkdir -p /var/service/pfrules2syslog/log

cat >> /var/service/pfrules2syslog/run << __EOF__
#!/bin/sh
#20130401 mhlavac: simple script to dump pf rules to syslog
exec 2> /dev/null
while [ 1 ]; do
  echo '-----'
  /sbin/pfctl -vv -sa
  sleep 900
  sleep \$(tr -cd 0-9 < /dev/random | head -c 2)
done
__EOF__
chmod +x /var/service/pfrules2syslog/run

cat >> /var/service/pfrules2syslog/log/run << __EOF__
#!/bin/sh
exec /usr/bin/logger -p local1.notice -i -t pfrules2syslog
__EOF__
chmod +x /var/service/pfrules2syslog/log/run

ln -s /var/service/pfrules2syslog /service/

The image is ready!
Reboot and enter the passphrase for the root partition.
 
Change passphrase, keys and the rest on a clone before deployment
Once we have our template ready to give away (e.g. to operations department), there are couple of things we have to do before getting a clone out of our hands. Changing the passphrase for the root partition is not enough, but the clone would be fully operational. If we don't do all the necessary changes right away, noone probably ever will.

This is what needs to be done after booting the clone before deploying it to production.

Code:
### Change hostname ###
hostname new.hostname.company.local
vi /etc/rc.conf
  #set hostname="new.hostname.company.local"

### Change GELI encryption passphrase for /dev/da0p5 (filesystem /) ###
geli setkey -n 0 /dev/da0p5

### Change GELI encryption key for gpt/varlog (filesystem /var/log) ###
# we overwrite the existing key
head -c32 /dev/random > /root/geli_keys/varlog.key-new
geli setkey -P -K /root/geli_keys/varlog.key-new -n 0 gpt/varlog
# if system reboots here (e.g. power failure), varlog.key-new has to be manually used to attach the device
mv /root/geli_keys/varlog.key-new /root/geli_keys/varlog.key

### change root password ###
passwd root

### Regenerate SSHd keys ###
rm -f /etc/ssh/ssh_host_*
service sshd restart

### Change the VLAN in ESX for attached interfaces ###
  #if necessary

### Change setting for em0 network interface ###
vi /etc/rc.conf
  #set ifconfig_em0="something useful"

### Change firewall settings ###
vi /usr/local/etc/pf-marwis.conf
adjust EXT_IP

# reload rules
pfctl -Fa -f /usr/local/etc/pf-marwis.conf

### Make sure SNMP credentials for Monitoring service are valid ###
service snmpd stop
#remove old user
rm /usr/local/share/snmp/snmpd.conf
vi /var/net-snmp/snmpd.conf
  # find and remove lines beginning with usmUser

# add new SNMP user
net-snmp-config --create-snmpv3-user \
                -ro -a SHA -A SUPERSECRETPASSWORD -x DES  new-snmpv3monitor
service snmpd start

### remove nonroot template users ###
pw userdel nonrootuser
pw groupdel nonrootuser
 
Back
Top