Saturday Aug 08, 2015

OpenLDAP + TLS in Solaris 11

This blog post serves as a followup to Configuring a Basic LDAP Server + Client in Solaris 11. It covers creating self-signed certificates and enabling TLS for secure communication.

1) Create certificates
# mkdir /etc/openldap/certs
# cd /etc/openldap/certs
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout server.key -out server.crt
# chmod 400 server.*
# chown openldap:openldap server.*
2) Update slapd.conf
Add the following lines to the end of /etc/openldap/slapd.conf

TLSCACertificateFile /etc/certs/ca-certificates.crt
TLSCertificateFile /etc/openldap/certs/server.crt
TLSCertificateKeyFile /etc/openldap/certs/server.key
3) Restart LDAP server
# svcadm disable ldap/server
# svcadm enable ldap/server
That's it! Connect to your LDAP server on port 389.

Tuesday Jan 14, 2014

Configuration Applications / OS's for 1MB ZFS Block Sizes

The latest release of the ZFS Storage Appliance, 2013.1.1.1, introduces 1MB block sizes for shares. This is a deferred update that can only be enabled inside of Maintenance → System. You can edit individual Filesystems or LUNs from within 'Shares' to enable the 1MB support (database record size).


This new feature may need additional tweaking on all connected servers to fully realize significant performance gains. Most operating systems currently do not support a 1MB transfer size by default. This can be very easily spotted within analytics by breaking down your expected protocol by IO size. As an example, let's look at a fibre channel workload being generated by an Oracle Linux 6.5 server:



The IO size is sitting at 501K, a very strange number that's eerily close to 512K. Why is this a problem? Well, take a look at our backend disks:


Our disk IO size (block size) is heavily fragmented! This causes our overall throughput to nosedive.


2GB/s is okay, but we can do better if our buffer size was 1MB on the host side.

Fixing the problem

Fibre Channel

# echo 'set maxphys=1048576' > /etc/system

Oracle Linux 6.5 uek3 kernel (previous releases do not support 1MB sizes for multipath)
# echo 1024 > /sys/block/dm*/queue/max_sectors_kb 

or create a permanent udev rule:

# vi /etc/udev/rules.d/99-zfssa.rules

ACTION=="add", SYSFS{vendor}=="SUN", SYSFS{model}=="*ZFS*", 
ENV{ID_FS_USAGE}!="filesystem", ENV{ID_PATH}=="*-fc-*", 
RUN+="sh -c 'echo 1024 > /sys$DEVPATH/queue/max_sectors_kb'"


QLogic [qlfc]
C:\> qlfcx64.exe -tsize /fc /set 1024

Emulex [HBAnyware]
set ExtTransferSize = 1

Please see MOS Note 1640013.1 for configuration for iSCSI and NFS.


After re-running the same FC workload with the correctly set 1MB transfer size, I can see the IO size is now where it should be.


This has a drastic impact on the block sizes being allocated on the backend disks:


And an even more drastic impact on the overall throughput:


A very small tweak resulted in a 5X performance gain (2.1GB/s to 10.9GB/s)! Until 1MB is the default for all physical I/O requests, expect to make some configuration changes on your underlying OS's.

System Configuration


  • 1 x Oracle ZS3-4 Controller
  • 2013.1.1.1 firmware
  • 1TB DRAM
  • 4 x 16G Fibre Channel HBAs
  • 4 x SAS2 HBAs
  • 4 x Disk Trays (24 4TB 7200RPM disks each)
  • 4 x Oracle x4170 M2 servers
  • Oracle Linux 6.5 (3.8.x kernel)
  • 16G DRAM
  • 1 x 16G Fibre Channel HBA


Each Oracle Linux server ran the following vdbench profile running against 4 LUNs:


This is a 70% read / 30% write sequential workload.

Wednesday Jul 10, 2013

Solaris 11 IPoIB + IPMP

I recently needed to create a two port active:standby IPMP group to be served over Infiniband on Solaris 11. Wow that's a mouthful of terminology! Here's how I did it:

List available IB links

[root@adrenaline ~]# dladm show-ib
net5         21280001CF4C96  21280001CF4C97  1    up     FFFF
net6         21280001CF4C96  21280001CF4C98  2    up     FFFF
Partition the IB links. My pkey will be 8001.
[root@adrenaline ~]# dladm create-part -l net5 -P 0x8001 p8001.net5
[root@adrenaline ~]# dladm create-part -l net6 -P 0x8001 p8001.net6
[root@adrenaline ~]# dladm show-part
LINK         PKEY  OVER         STATE    FLAGS
p8001.net5   8001  net5         unknown  ----
p8001.net6   8001  net6         unknown  ----
Create test addresses for the newly created datalinks
[root@adrenaline ~]# ipadm create-ip p8001.net5
[root@adrenaline ~]# ipadm create-addr -T static -a p8001.net5/ipv4
[root@adrenaline ~]# ipadm create-ip p8001.net6
[root@adrenaline ~]# ipadm create-addr -T static -a p8001.net6/ipv4
[root@adrenaline ~]# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
p8001.net5/ipv4   static   ok 
p8001.net6/ipv4   static   ok 
Create an IPMP group and add the IB datalinks
[root@adrenaline ~]# ipadm create-ipmp ipmp0
[root@adrenaline ~]# ipadm add-ipmp -i p8001.net5 -i p8001.net6 ipmp0
Set one IB datalink to standby
[root@adrenaline ~]# ipadm set-ifprop -p standby=on -m ip p8001.net6
Assign an IP address to the IPMP group
[root@adrenaline ~]# ipadm create-addr -T static -a ipmp0/v4
That's it! Final checks:
[root@adrenaline ~]# ipadm
NAME              CLASS/TYPE STATE        UNDER      ADDR
ipmp0             ipmp       ok           --         --
   ipmp0/v4       static     ok           --
p8001.net5        ip         ok           ipmp0      --
   p8001.net5/ipv4 static    ok           --
p8001.net6        ip         ok           ipmp0      --
   p8001.net6/ipv4 static    ok           --

[root@adrenaline ~]# ping is alive

Thursday Feb 21, 2013

Configuring a Basic LDAP Server + Client in Solaris 11

Configuring the Server
Solaris 11 ships with OpenLDAP to use as an LDAP server. To configure, you're going to need a simple slapd.conf file and an LDIF schema file to populate the database. First, let's look at the slapd.conf configuration:
# cat /etc/openldap/slapd.conf
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema

pidfile         /var/openldap/run/
argsfile        /var/openldap/run/slapd.args

database        bdb
suffix          "dc=buford,dc=hillvalley"
rootdn          "cn=admin,dc=buford,dc=hillvalley"
rootpw          secret
directory       /var/openldap/openldap-data
index           objectClass     eq
You may want to change the lines suffix and rootdn to better represent your network naming schema. My LDAP server's hostname is buford and domain name is hillvalley. You will need to add additional domain components (dc=) if the name is longer. This schema assumes the LDAP manager will be called admin. Its password is 'secret'. This is in clear-text just as an example, but you can generate a new one using slappasswd:
[paulie@buford ~]$ slappasswd
New password: 
Re-enter new password: 
Replace 'secret' with the entire hash, {SSHA}MlyFaZxG6YIQ0d/Vw6fIGhAXZiaogk0G, for the rootpw line. Now, let's create a basic schema for my network.
# cat /etc/openldap/schema/hillvalley.ldif
dn: dc=buford,dc=hillvalley
objectClass: dcObject
objectClass: organization
o: bufford.hillvalley
dc: buford

dn: ou=groups,dc=buford,dc=hillvalley
objectCLass: top
objectClass: organizationalunit
ou: groups

dn: ou=users,dc=buford,dc=hillvalley
objectClass: top
objectClass: organizationalunit
ou: users

dn: cn=world,ou=groups,dc=buford,dc=hillvalley
objectClass: top
objectClass: posixGroup
cn: world
gidNumber: 1001

dn: uid=paulie,ou=users,dc=buford,dc=hillvalley
objectClass: top
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: Paul Johnson
uid: paulie
uidNumber: 1001
gidNumber: 1001
homeDirectory: /paulie/
loginShell: /usr/bin/bash
userPassword: secret
I've created a single group, world, and a single user, paulie. Both share the uid and gid of 1001. LDAP supports lots of additional variables for configuring a user and group account, but I've kept it basic in this example. Once again, be sure to change the domain components to match your network. Feel free to also change the user and group details. I've left the userPassword field in clear-text as 'secret'. The same slappasswd method above applies here as well. It's time to turn on the server, but first, let's change some ownership permissions:
[paulie@buford ~]$ sudo chown -R openldap:openldap /var/openldap/
... and now ...
[paulie@buford ~]$ sudo svcadm enable ldap/server
Check that it worked:
[paulie@buford ~]$ svcs | grep ldap
online         12:13:49 svc:/network/ldap/server:openldap_24
Neat, now let's add our schema file to the database:
[paulie@buford ~]$ ldapadd -D "cn=admin,dc=buford,dc=hillvalley" -f /etc/openldap/schema/hillvalley.ldif
Enter bind password: 
adding new entry dc=buford,dc=hillvalley
adding new entry ou=groups,dc=buford,dc=hillvalley
adding new entry ou=users,dc=buford,dc=hillvalley
adding new entry cn=world,ou=groups,dc=buford,dc=hillvalley
adding new entry uid=paulie,ou=users,dc=buford,dc=hillvalley
That's it! Our LDAP server is up, populated, and ready to authenticate against.

Configuring the Client
I'm going to turn my example server, buford.hillvalley, into an LDAP client as well. To do this, we need to run the `ldapclient` command to map our new user and group data:
[paulie@buford ~]$ ldapclient manual \
-a credentialLevel=proxy \
-a authenticationMethod=simple \
-a defaultSearchBase=dc=buford,dc=hillvalley \
-a domainName=buford.hillvalley \
-a defaultServerList= \
-a proxyDN=cn=admin,dc=buford,dc=hillvalley \
-a proxyPassword=secret \
-a attributeMap=group:gidnumber=gidNumber \
-a attributeMap=passwd:gidnumber=gidNumber \
-a attributeMap=passwd:uidnumber=uidNumber \
-a attributeMap=passwd:homedirectory=homeDirectory \
-a attributeMap=passwd:loginshell=loginShell \
-a attributeMap=shadow:userpassword=userPassword \
-a objectClassMap=group:posixGroup=posixgroup \
-a objectClassMap=passwd:posixAccount=posixaccount \
-a objectClassMap=shadow:shadowAccount=posixaccount \
-a serviceSearchDescriptor=passwd:ou=users,dc=buford,dc=hillvalley \
-a serviceSearchDescriptor=group:ou=groups,dc=buford,dc=hillvalley \
-a serviceSearchDescriptor=shadow:ou=users,dc=buford,dc=hillvalley
As usual, change the host and domain names as well as the IP address held in defaultServerList and the proxyPassword. The command should respond back that the system was configured properly, however, additional changes will need to be made if you use DNS for hostname lookups (most people use DNS, so run these commands).
svccfg -s name-service/switch setprop config/host = astring: \"files dns ldap\"
svccfg -s name-service/switch:default refresh
svcadm restart name-service/cache
Now, we need to change how users login so that the client knows that there is an extra LDAP server to authenticate against. This should not lockout local worries. Examine the two files /etc/pam.d/login and /etc/pam.d/other. Change any instance of
auth required  
auth binding   server_policy
After this line, add the following new line:
auth required 
That's it! Finally, reboot your system and see if you can login with your newly created user.

Update: Glenn Faden wrote an excellent guide to configuring OpenLDAP using the native Solaris user/group/role management system.

Monday Feb 11, 2013

Recovering Passwords in Solaris 11

About once a year, I'll find a way to lock myself out of a Solaris system. Here's how to get out of this scenario. You'll need a Solaris 11 Live CD or Live USB stick.
  • Boot up from the Live CD/USB
  • Select the 'Text Console' option from the GRUB menu
  • Login to the solaris console using the username/password of jack/jack
  • Switch to root
  • $ sudo su
    password jack
  • Mount the solaris boot environment in a temporary directory
  • # beadm mount solaris /a
  • Edit the shadow file
  • # vi /a/etc/shadow
  • Find your username and remove the password hash
  • Convert
  • Allow empty passwords at login
  • $ vi /a/etc/default/login
    Switch this line
  • Update the boot archive
  • # bootadm update-archive -R /a
  • Reboot and remove the Live CD/USB from system
  • # reboot
    If prompted for a password, hit return since this has now been blanked.

Monday Feb 20, 2012

CIFS Sharing on Solaris 11

Things have changed since Solaris 10 (and Solaris 11 Express too!) on how to properly set up a CIFS server on your Solaris 11 machine so that Windows clients can access files. There's some documentation on the changes here, but let me share the full instructions from beginning to end.
hostname: adrenaline
username: paulie
poolname: pool
mountpnt: /pool
share: mysharename
  • Install SMB server package
  • [paulie@adrenaline ~]$ sudo pkg install service/file-system/smb
  • Create the name of the share
  • [paulie@adrenaline ~]$ sudo zfs set share=name=mysharename,path=/pool,prot=smb pool
  • Turn on sharing using zfs
  • [paulie@adrenaline ~]$ sudo zfs set sharesmb=on pool
  • Turn on your smb server
  • [paulie@adrenaline ~]$ sudo svcadm enable -r smb/server
  • Check that the share is active
  • [paulie@adrenaline ~]$ sudo smbadm show-shares adrenaline
    Enter password: 
    c$                  Default Share
    IPC$                Remote IPC
    3 shares (total=3, read=3)
  • Enable an existing UNIX user for CIFS sharing (you may have to reset the password again eg.`passwd paulie` )
  • [paulie@adrenaline ~]$ sudo smbadm enable-user paulie
  • Edit pam to allow for smb authentication (add line to end of file)
  • Solaris 11 GA only:
    [paulie@adrenaline ~]$ vi /etc/pam.conf
    other   password required nowarn
    Solaris 11 U1 or later:
    [paulie@adrenaline ~]$ vi /etc/pam.d/other
    password required nowarn
  • Try to mount the share on your Windows machine
  • \\adrenaline\mysharename

Tuesday May 31, 2011

Compiling Alpine on Solaris 11

I use alpine as my primary e-mail client. In order to get it compiled for Solaris 11 (snv_166 and later), you will need to make a few changes to the source.
[paulie@adrenaline ~]$ uname -orv
5.11 snv_166 Solaris
[paulie@adrenaline ~]$ ./configure --with-ssl-include-dir=/usr/include/openssl
[paulie@adrenaline ~]$ gmake
We run into a problem ...
In file included from osdep.c:66:
scandir.c: In function `Scandir':
scandir.c:45: error: structure has no member named `dd_fd'
Let's investigate:
[paulie@adrenaline ~]$ vi /usr/include/dirent.h
#if defined(__USE_LEGACY_PROTOTYPES__)
/* traditional SVR4 definition */
typedef struct {
        int     dd_fd;          /* file descriptor */
        int     dd_loc;         /* offset in block */
        int     dd_size;        /* amount of valid data */
        char    *dd_buf;        /* directory block */
} DIR;                          /* stream data from opendir() */
/* default definition (POSIX conformant) */
typedef struct {
        int     d_fd;           /* file descriptor */
        int     d_loc;          /* offset in block */
        int     d_size;         /* amount of valid data */
        char    *d_buf;         /* directory block */
} DIR;                          /* stream data from opendir() */
#endif  /* __USE_LEGACY_PROTOTYPES__ */
Interesting, so alpine *should* be using POSIX instead of the older UNIX SVR4 definitions. Let's make a change to the scandir.c file, which is located in alpine-2.00/imap/c-client/scandir.c. On line 45 I see the following use of dd_fd:
  if ((!dirp) || (fstat (dirp->dd_fd,&stb) < 0)) return -1;
Let's change that dd_fd to d_fd.
  if ((!dirp) || (fstat (dirp->d_fd,&stb) < 0)) return -1;
After recompile, everything works as expected. I'm sure there is a better way of fixing this problem, but considering how trivial this issue is, a small edit is sufficient.

Monday Jan 03, 2011

ZFS Encryption for USB sticks on Solaris 11 Express

USB memory sticks are easily lost, so to keep your data safe, it's best to use the new encryption feature of ZFS available since snv_149 (ZFS version 30). Here's how to take advantage of it.
[paulie@adrenaline ~]$ uname -a
SunOS adrenaline 5.11 snv_155 i86pc i386 i86pc Solaris
Get the device id for the USB stick using rmformat.
[paulie@adrenaline ~]$ rmformat
Looking for devices...
     1. Logical Node: /dev/rdsk/c11t0d0p0
        Physical Node: /pci@0,0/pci108e,534a@2/hub@4/storage@1/disk@0,0
        Connected Device: SanDisk  U3 Cruzer Micro  8.02
        Device Type: Removable
	Bus: USB
	Size: 1.9 GB
	Access permissions: Medium is not write protected.
The device id is c11t0d0p0. Using this id, we can make a pool on the device called 'secret'. You can call yours whatever you want.
[paulie@adrenaline ~]# zpool create -O encryption=on secret c11t0d0p0
Enter passphrase for 'secret': 
Enter again: 
Let's create a random 128MB file in the new pool called file.enc.
[paulie@adrenaline ~]# cd /secret; mkfile 128m file.enc
Now, let's make sure it works by exporting and importing the secret pool and hope it asks for a password.
[paulie@adrenaline ~]# zpool export secret
[paulie@adrenaline ~]# zpool import secret
Enter passphrase for 'secret': 
It works as expected. Let's check for the created file.
[paulie@adrenaline ~]# ls /secret
We can also check the encryption of any zfs filesystem by using the following command:
[paulie@adrenaline ~]# zfs get encryption secret
secret  encryption  on           local
For more information visit:

Friday Jun 11, 2010

Flash Player 10.1 RC available for Solaris / OpenSolaris

Adobe Flash Player 10.1 RC is now available as a prerelease. This version does not require the medialib dependency and should work on its own after installation. You can find it at the Adobe Labs site.

$ wget
$ bzip2 -d flashplayer10_1_rc1_solaris_x86_061010.tar.bz2
$ tar xvf flashplayer10_1_rc1_solaris_x86_061010.tar
$ mkdir -p ~/.mozilla/plugins/
$ mv flash_player_solaris_10_1_53_64_x86/ ~/.mozilla/plugins/
$ pfexec mv flash_player_solaris_10_1_53_64_x86/ /usr/lib/firefox/plugins/
$ wget
Follow x86 directions above

Wednesday Jun 09, 2010

"Cannot open device" Error

On occasion if you are trying to fdisk or mount a USB disk on Solaris 10 you may get an error that says "Cannot open device." For example:
# fdisk /dev/rdsk/c2t0d0s2
Cannot open device
Things to check:
  • 1. Make sure you are root or have the correct user privilege
  • 2. Try `devfsadm -Cv` to remove any stale disk entries
  • 3. Stop volume management `svcadm disable volfs`

Wednesday Apr 28, 2010

Packages Renamed in OpenSolaris

If you have been using the package management system in the newest builds of OpenSolaris (b133+), you may have noticed the naming scheme changes that affect new and existing packages. [Full list of changes]

For example, trying to find the usb header file package is a bit trickier. These files, namely usba.h, usbai.h, and usbdevs.h, are not installed into /usr/include/sys/usb in the default installation. To retrieve them, use this command:

$ pfexec pkg install header-usb

In previous version, these files could have been obtained from either SUNWusbu or SUNWsfwhea. The removal of the SUNW prefix is the most apparent name change for the package collection. Now you can get busy building the latest apcupsd version!

Tuesday Feb 09, 2010

Retrieving MAC Address in Solaris using C as a non-root user

I needed to find a way to get the physical (MAC) address using C. From what I could gather from searching, there are two methods for retrieving it: libdlpi and arp. libdlpi is the more elegant solution as it requires a simple call to dlpi_get_physaddr(). This is how ifconfig prints your network interface's MAC address. Unfortunately, libdlpi calls are only permitted as root.

As explained by James Carlson:

The reason it was like this was historical: getting the MAC address in
ifconfig meant opening up the DLPI node and talking to the driver. As
the drivers didn't have discrete privileges for each operation, and
you had to be almighty root to touch them, 'ifconfig' didn't show the
MAC address when not privileged.

The second solution is to use arp. In Solaris you can determine the physical address by looking at the arp tables directly (`arp -a | grep <INTERFACE>` or `netstat -p | grep <INTERFACE>`). With C, this can be done by using the if sockets and arp libraries.

I wrote up a solution called "getmac" using both methods. You can gather it here.

  • Directions
    $ wget
    $ gcc getmac.c -o getmac -lsocket -ldlpi
    $ ./getmac <interface_name>
    arp:	ffffffffffff
    dlpi:	dlpi failure, are you root?
    $ pfexec ./getmac <interface_name>
    arp:	ffffffffffff
    dlpi:	ffffffffffff
Remember to use pfexec for the libdlpi method.

Thursday Jan 21, 2010

OpenSolaris + Fit-PC2 + Mediasonic Pro Box 4 Bay Enclosure

After the failure of the SATA and USB ports on my Intel D945GCL Atom board, I decided to build out a new file server. Sticking to the Atom theme, I decided to go small and get the CompuLab FIT-PC2. This little toy uses the Z530 1.6Ghz CPU that apparently uses only 6 watts of power. I'm assuming that means *without* a hard drive installed.

Measuring in at around 115 x 101 x 27mm (~ 4.5"x4.0"x1.0"), it is only big enough to hold one laptop sized 2.5" SATA drive.

The drive I installed only has 80GB of space. That would run out real quick with my needs, so I decided to get a MediaSonic USB disk enclosure to link up with my server. It can hold up to 4 SATA drives.

The PC sits on top of the enclosure on my bookshelf taking up 8.5" x 5.0" x 6.5" amount of space. This is not only power efficient, but space efficient since I am using 4 x 1TB drives. 4TB total (theoretical), ~2.6TB in a ZFS raidz. If I were to have purchased the 2TB drives, it would be even better.

Doug's blog on the FIT-PC2 gives a good overview on the features of the device and what works. There is no wifi driver and Xorg doesn't work, so you may want to install OpenSolaris on another machine before installing the internal HDD. My server is headless and uses the built-in gigabit ethernet, so I don't care about those issues.

Links and prices Total = $748

Wednesday Dec 09, 2009

Can't use NumPad in OpenSolaris?

Today I thought I broke the numpad on my keyboard; none of then numbers were working. Switching on and off the Num Lock key didn't work. However, anytime I hit a number and held the key down, the mouse cursor would move across the screen. By some sort of black magic, I found a secret keyboard combo to turn on Mouse control via keypad.

Solution to turn it off
System ⇾ Preferences ⇾ Assistive Technologies ⇾ Keyboard Accessibility ⇾ Mouse Keys

Uncheck 'Pointer can be controlled using the keypad'
I must admit, however, this can be a handy feature when working with a mouse-less machine.

Wednesday Nov 25, 2009

Latex for OpenSolaris

Ever wanted to experiment with latex to write a paper or redesign your resume, but unsure how to install a latex package or compose a latex document? I'll try to explain it simply using OpenSolaris.

Install Latex

d its dependencies from our friends at
cd /tmp
gzip -d \*.gz
  • Install the packages
  • pfexec pkgadd -d libgcc-3.3-sol10-intel-local
    pfexec pkgadd -d ncurses-5.6-sol10-x86-local
    pfexec pkgadd -d libiconv-1.11-sol10-x86-local
    pfexec pkgadd -d tetex-3.0-sol10-x86-local

    Play with Latex
    For my simple uses of latex, I use two binaries to compose my documents: latex and dvipdf. Latex requires a tex file to generate a document. For this example, I will use my favorite resume template created by David Grant.
    cd /tmp
    mv resume.tex.txt resume.tex
    mv shading.sty.txt shading.sty
    Now, let's use the binaries I mentioned earlier to create a pdf file.
    /usr/local/teTeX/bin/i386-pc-solaris2.10/latex resume.tex
    /usr/local/teTeX/bin/i386-pc-solaris2.10/dvipdft resume.dvi
    You should find a pdf file in /tmp called resume.pdf. View it with acroread or evince to get an idea of how awesome latex is. I won't go into too much detail on how to create the resume.tex file, but viewing and editing it will you give you a good understanding on its syntax. This is David's resume that is generated:

    Hiya, my name is Paul Johnson and I'm a software engineer working on the Oracle ZFS Storage Appliance .


    « August 2015