Index by title

About Dyson

Dyson is a general-purpose operating system, a Debian derivative using the illumos kernel, libc, and SMF init system (formerly OpenSolaris). See FAQ.

It is not a successor of any existing or existed distributions based on illumos or OpenSolaris. Dyson is constructed from scratch to be like Debian as much as possible. Namely, most of Debian packages can be built on Dyson without any changes, and arch-independent packages (arch all in Debian terms) can be installed directly as is.

Project goals:
  1. General-purpose operating system with OpenSolaris kernel (for desktops and servers)
  2. Port GNU GLibc
  3. Official Debian port
  4. Hijack illumos mainstream.

Get Dyson

Currently Dyson only runs on x86_64 processors (it is fully 64-bit).
There is a LiveCD ISO image with a simple installer:

For downloading and using Dyson consider using the mirrors.

VCS repositories are available for anonymous read-only access:

Debian patch tracker:

If the APT repository cannot be verified due to missed public key (The following signatures couldn't be verified because the public key is not available: NO_PUBKEY),
get current singing key located at and use "apt-key" to add the key manually.
This key is usually automatically installed with the "dyson-archive-keyring" package.

It is possible to use Vagrant to set up a VirtualBox machine. See

Mailing lists - development of Dyson, technical topics, packaging, porting Debian packages, porting software to illumos.

Get involved

Try it. Report issues and wishes. Feel free to email to

Port Debian packages and various software to Dyson. Send patches to upstream and/or Debian package maintainers. Ideally any Debian package should need no more than a simple rebuild. See Porting guide.

See to find out if you can help with an advise or coding.

Things to be done:


Assume Debian (Linux) to Dyson.

APT repository

Dyson's APT repository includes pre-compiled packages for Debian (Linux / amd64). Add this line to /etc/apt/sources.list:

deb [ arch=amd64 ] unstable main

Building binutils

Both normal and cross binutils should be installed on Debian (Linux) system. Thus original (not patched) version of binutils is overwritten by the Dyson's binutils. This is pretty safe, because Dyson's patches only affect Solaris targets, also Dyson's binutils are usually newer that Debian's.

  1. Get binutils source package from (you need version patched for Dyson), e. g.:
    $ dget -u
  2. Build normal binutils:
    $ cd binutils-2.28
    $ ./debian/rules stamps/control
    $ dpkg-buildpackage --build=any
  3. Build cross binutils. According to debian/README.cross it's quite simple:
    $ cd binutils-2.28
    $ TARGET=x86_64-pc-solaris2.11 ./debian/rules stamps/control
    $ TARGET=x86_64-pc-solaris2.11 dpkg-buildpackage --build=any
  4. Result:
    find debian/binutils-x86-64-pc-solaris2.11 -depth -newermt 'Sat, 13 May 2017 13:33:58 +0300' -print0 | \
        xargs -0r touch --no-dereference --date='Sat, 13 May 2017 13:33:58 +0300'
    dpkg --build debian/binutils-x86-64-pc-solaris2.11 ..
    dpkg-deb: building package 'binutils-x86-64-pc-solaris2.11' in '../binutils-x86-64-pc-solaris2.11_2.28-5+dyson1_amd64.deb'.
    $ dpkg -c ../binutils-x86-64-pc-solaris2.11_2.28-5+dyson1_amd64.deb
    drwxr-xr-x root/root         0 2017-05-13 13:33 ./
    drwxr-xr-x root/root         0 2017-05-13 13:33 ./usr/
    drwxr-xr-x root/root         0 2017-05-13 13:33 ./usr/bin/
    -rwxr-xr-x root/root     28176 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-addr2line
    -rwxr-xr-x root/root     56856 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-ar
    -rwxr-xr-x root/root    369928 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-as
    -rwxr-xr-x root/root     23776 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-c++filt
    -rwxr-xr-x root/root   3064344 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-dwp
    -rwxr-xr-x root/root     28160 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-elfedit
    -rwxr-xr-x root/root     93144 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-gprof
    -rwxr-xr-x root/root   1185712 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-ld
    hrwxr-xr-x root/root         0 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-ld.bfd link to ./usr/bin/x86_64-pc-solaris2.11-ld
    -rwxr-xr-x root/root   5206392 2017-05-13 13:33 ./usr/bin/
    -rwxr-xr-x root/root     41192 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-nm
    -rwxr-xr-x root/root    222448 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-objcopy
    -rwxr-xr-x root/root    353144 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-objdump
    -rwxr-xr-x root/root     56856 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-ranlib
    -rwxr-xr-x root/root    494112 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-readelf
    -rwxr-xr-x root/root     28024 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-size
    -rwxr-xr-x root/root     28144 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-strings
    -rwxr-xr-x root/root    222456 2017-05-13 13:33 ./usr/bin/x86_64-pc-solaris2.11-strip
    drwxr-xr-x root/root         0 2017-05-13 13:33 ./usr/lib/
    drwxr-xr-x root/root         0 2017-05-13 13:33 ./usr/lib/x86_64-linux-gnu/
    -rw-r--r-- root/root   1234664 2017-05-13 13:33 ./usr/lib/x86_64-linux-gnu/
    -rw-r--r-- root/root   1661968 2017-05-13 13:33 ./usr/lib/x86_64-linux-gnu/

Building GCC

To be done

Dyson Installer


To install Dyson you need:

You can also use virtual machines such as VirtualBox or QEMU.

Installing on QEMU

This is tested on Debian amd64 with QEMU version 1.1.2.

$ qemu-img create -f qcow2 dyson.qcow2 10G
$ qemu-system-x86_64 -hda dyson.qcow2 -m 1500 -cdrom dyson-netinst-2013-05-05-1506.iso

Getting the installer

Download the lastest ISO image of install CD from

Network access from the install CD

When booting from CD the startup script tries to bring networking up via DHCP.

If no DHCP servers available you have to configure network manually. To configure network manually switch to the console (press the F2 key), and use commands dladm, ipadm, route, also remember to update the /etc/resolv.conf file with vim or nano. See appropriate man pages, e. i. man ipadm, for detail.


  1. Print available network interfaces:
    # dladm show-phys
    LINK         MEDIA                STATE      SPEED  DUPLEX    DEVICE
    e1000g0      Ethernet             unknown    1000   full      e1000g0
  2. Bring the "e1000g0" interface up (aka plumb):
    # ipadm create-if e1000g0

    A few seconds later, if you type dladm show-phys again, you will see that the state of the interface is changed from "unknown" to "up" or "down" (cable connected or not). If the state is "down" there is no reason to go with this interface until you connect the cable.
  3. Assign an address to the interface. You may want to try DHCP again:
    # ipadm create-addr -T dhcp e1000g0/dhcp

    or give it a static address, e. g.:
    # ipadm create-addr -T static -a e1000g0/static
  4. If using static IP, set up the default gateway (e. g., otherwise dhcpagent will do it for you:
    route -n add default -gateway

    You can view routing table with netstat:
    netstat -nr
  5. Setup name servers in /etc/resolv.conf

Getting closed source drivers

Dyson does not include closed source drivers, such as mpt (see
There are instruction by Jason Upton on how to get closed source drivers and use them during installation:

Post-install configuration

Getting updates

Since the installer is a network installer it uses "testing" repository to install base system. "testing" repository is known to work. After installation you may want to switch to "unstable".

Dual boot with GRUB2 on Debian

Given that Dyson is installed on the primary partition N of the first drive, add following lines to /etc/grub.d/40_custom and run grub-mkconfig -o /boot/grub/grub.cfg to updated GRUB2 menu.

menuentry "Dyson" {
set root=(hd0,N) # change N to the partition number (1 to 4)
chainloader +1

With this configuration Debian's GRUB2 will show the "Dyson" item in its menu and will run Dyson's GRUB if you choose that item ("chain loading").

Obviously, Dyson's GRUB should be installed into a partition, not into MBR (Debian's GRUB2 holds MBR).

Installation process

This section describes an optimistic installation process on a clean virtual machine.

LiveCD GRUB menu:

LiveCD is booting:

The installer's start screen:

The console. You can switch to the console (press F2) and execute any commands as root. To switch back to the installer press F1:

First of all, the installer searches for hard disks and ZFS pools. The installer can install Dyson to existing ZFS pool, or can create a new one.

For new ZFS pool you need a disk with one Solaris partition:

cfdisk from util-linux is used for editing partitions :

Solaris partition has id = 0xbf:

After creating a Solaris partirion remember to choose "Write" in cfdisk menu, then - "Quit":

Now you are ready to install Dyson:

The installer will format Solaris partition (with a single slice) and create ZFS root pool and minimal ZFS filesystems (including swap, /home and /):

Choosing how big the installed system will be:

Then you will be asked to choose a Dyson mirror:

Next, installation of a base system begins (using debootstrap):

If you choose basic or desktop profile, additional packages will be installed (via apt-get):

Then - enter a hostname (aka nodename):

And finally, enter root password:

If installing more than just a minimal system, you will be asked to create a regular user:

Then the installer will create boot archive:

And populate initial SMF repository:

Dyson uses GRUB 1 for booting (aka GRUB legacy). It can be installed on master boot record (MBR) or on a partitions (which you've choosen for root ZFS pool). Note that is that partition is a logical partition, GRUB will be forcedly installed on MBR. If you are installing on an existing ZFS pool (e. g. created by OpenIndiana), you may want to just update GRUB menu, or completely skip GRUB configuration. In any case an example configuration is saved in /boot/grub/menu.lst on root filesystem.

Then, you are done:

Eject CD and reboot:

That was just the beginning...

How to

Prevent X11 from starting

Lightdm is the default desktop manager. It is started by the svc:/system/graphical-login:lightdm SMF service. Disable it to disable X11 autostart.

Switch to a virtual terminal

Make sure vtdaemon is installed and svc:/system/vtdaemon:default is enabled. Enable the svc:/system/console-login:vt2 SMF service for virtual terminal 2. Use CTRL+ALT+F2 to switch to VT 2.

Dyson mirrors


Thanks to Yandex.

The Netherlands

Thanks to NLUUG and Mike Hulsman.
Synchronised every 2 hours on the even hours.


Thanks to
Synchronised every 4 hours.


This is the primary site:

Creating new mirrors

Mirrors can be created with rsync:

Particular recipes

Missing d_type of struct dirent


inputoutput.cpp:82:27: error: ‘struct dirent’ has no member named ‘d_type’; did you mean ‘d_name’? 
                 if (dirp->d_type == DT_REG)                                   
inputoutput.cpp:82:37: error: ‘DT_REG’ was not declared in this scope
                 if (dirp->d_type == DT_REG)

Solution is to use dirfd and fstatat, as shown below.
Note that decent programs should use stat/fstat/fstatat anyway, because not checking d_type == DT_UNKNOWN is a bug!

--- opencv-
+++ opencv-
@@ -7,6 +7,7 @@
     #include <tchar.h>
     #include <dirent.h>
+    #include <sys/stat.h>

 namespace cv
@@ -72,14 +73,18 @@ namespace cv
             DIR *dp;
             struct dirent *dirp;
+            int dfd;
+            struct stat st;
             if((dp = opendir(path.c_str())) == NULL)
                 return list;
+            dfd = dirfd(dp);

             while ((dirp = readdir(dp)) != NULL)
-                if (dirp->d_type == DT_REG)
+                if ((0 == fstatat(dfd, dirp->d_name, &st, 0)) &&
+                    S_ISREG(st.st_mode))
                     if ("*") == 0)

struct ifreq

If struct ifreq causes problems (e. g. missing ifr_ifindex) consider using struct lifreq, see for example

Too many arguments to function ‘getpwuid_r’, etc.


Missing strverscmp()

Use libiberty-dev package: link with -liberty, include libiberty/libiberty.h. The only known package with such a problem is tree (actually it includes strverscmp.c).

Debian symbols file

glibc defines FILE as _IO_FILE, illumos libc - as __FILE.
So C++ functions differ, and dh_makeshlibs can fail:

dpkg-gensymbols: warning: some new symbols appeared in the symbols file: see diff output below
dpkg-gensymbols: warning: some symbols or patterns disappeared in the symbols file: see diff output below
dpkg-gensymbols: warning: debian/libqt5webkit5/DEBIAN/symbols doesn't match completely debian/libqt5webkit5.symbols
dh_makeshlibs: failing due to earlier errors


@@ -2182,7 +2182,8 @@ libqt5webkit5 #MINVER#
  _ZN3JSC7JSProxy9setTargetERNS_2VMEPNS_14JSGlobalObjectE@Base 5.2.0
  _ZN3JSC7JSScope13objectAtScopeEPS0_@Base 5.0.2
  _ZN3JSC7JSValue13isValidCalleeEv@Base 5.0.2
- _ZN3JSC7Options14dumpAllOptionsEP8_IO_FILE@Base 5.0.2
+ (arch=!illumos-amd64)_ZN3JSC7Options14dumpAllOptionsEP8_IO_FILE@Base 5.0.2
+ (arch=illumos-amd64)_ZN3JSC7Options14dumpAllOptionsEP6__FILE@Base 5.2.1+dfsg-6~dyson1
  _ZN3JSC7Options9s_optionsE@Base 5.0.2
  _ZN3JSC7Options9setOptionEPKc@Base 5.0.2
  _ZN3JSC7Profile10restoreAllEv@Base 5.0.2

Getting stack boundaries

On Linux we usually use pthread_getattr_np(), on Dyson we have thr_stksegment().

Be careful: if stack is "unlimited", ss_size will hold RLIM_INFINITY = -3 (see sys/resource.h) which definitely must not be interpreted as stack size! In this case lower stack boundary should be set to 0xFFFF800000000000L.

Example from Mono:

#elif (defined(__sun__) || defined(__illumos_kernel__))
#include <thread.h>
#include <errno.h>
        int rc;
        stack_t s;

        do {
            rc = thr_stksegment(&s);
        } while (rc != 0 && errno == EAGAIN);

        info->stack_end = s.ss_sp;

        // Is stack "unlimited" ?
        if (s.ss_size == RLIM_INFINITY)
            // XXX Lower stack boundary
            info->stack_start_limit = (void*)0xFFFF800000000000L;
            info->stack_start_limit = (void*)((intptr_t)s.ss_sp - (intptr_t)s.ss_size);

P. S. pthread_attr_get_np() is provided by libc since 5.10.18.git.2a44663-4 (2017-11-22).

Getting path of executable

Use const char * getexecname() from stdlib.h or

readlink("/proc/self/path/a.out", buf, bufsize);

Conflicting declarations of abs() in C++ sources


In file included from ../../src/base/dict.h:40:0,
                 from freetype.cpp:152:
/usr/include/c++/4.8/cstdlib: In function ‘long long int std::abs(long long int)’:
/usr/include/c++/4.8/cstdlib:174:20: error: declaration of C function ‘long long int std::abs(long long int)’ conflicts with
   abs(long long __x) { return __builtin_llabs (__x); }
In file included from /usr/include/stdlib.h:38:0,
                 from ../../include/Inventor/SoType.h:37,
                 from ../../include/Inventor/errors/SoError.h:39,
                 from ../../include/Inventor/errors/SoDebugError.h:36,
                 from ../../src/coindefs.h:95,
                 from freetype.cpp:44:
/usr/include/iso/stdlib_iso.h:122:12: error: previous declaration ‘int std::abs(int)’ here
 extern int abs(int);

Make sure C++ sources include cstdlib, not stdlib.h.

Missing IXDR_GET_LONG or similar *_LONG RPC macros

These macros are deprecated and removed from 64-bit Solaris or illumos. Glibc provides them via *_INT32 macros. Workaround:

#include <rpc/xdr.h>

// ...

#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf))

#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v)))

#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf))

#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v))

Boost threads unavailable on this platform

See /usr/include/boost/config/platform/solaris.hpp: -D_PTHREADS must be defined, use g++ -pthread

C library

For a while Dyson uses illumos libc, not GNU libc.

More libraries to link

Some functions, expected to be in libc, really are in libsocket, libnsl and libresolv. Also Dyson uses GNU libiconv.

$ cat /usr/lib/x86_64-illumos/
INPUT( AS_NEEDED(-lsocket -lnsl -lresolv -liconv))

Note, that this breaks sunld (illumos link editor). The same trick is used in Debian for libncurses.

Less libraries to link

librt, libphtread, libdl are dummy ("filters"). There is not need to link with these libraries, all functions expected to be in these libraries are in libc or (not worry either).

Extended attributes

There are specific functions to work with extended attributes of files. These functions involve illumos library libnvpair. Functions known from Linux are provided by libattr (see #59).

See particular recipes.

Filesystem layout

/bin is a symbolic link to /usr/bin

illumos and Solaris have been using it for a long time. GNU/Linux is going to use it too. But now in Debian /bin and /usr/bin are separated. So additional modifications are required for some "low-level" packages like "sed", "ed", all shells, etc.

Debian multiarch

So Dyson on amd64 has directories /lib/x86_64-illumos and /usr/lib/x86_64-illumos.

Manpages layout

Some packages (e. g. "sudo") detect "SunOS" and put manpages in different directories, and dh_install cannot find some manpages after that. Debian man page layout (aka GNU-style) is prefered.


Default compiler is GCC 9

The first version of GCC supporting x86_64-pc-solaris2.11 hosts is 4.7

GNU linker (ld) from GNU binutils is the default linker

Some packages fondly expect that if uname returns "SunOS", the linker is the SunOS linker.
It is wrong, see for example:

kbuild used to pass the "-i" to the linker; for sun ld this means "Ignore the LD_LIBRARY_PATH", for GNU ld - "Incremental link".

Init system is SMF

Logrotate rules need attention

Some rules for logrotate run init-scripts for sysvinit, e. g. Apache and Lighttpd.

Rebuild script


# ./rebuild pandoc
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Build-Depends dependency for pandoc cannot be satisfied because candidate version of package libghc-aeson-dev can't satisfy version requirements

# ./rebuild libghc-aeson-dev


Non-interactively update a package from Debian source repository.


APT repositories

# cat /etc/apt/sources.list
deb unstable main
deb-src sid main

Signing result

Add your GPG key to GPG agent to bypass passphrase



login= pashev
method= scp
incoming= /srv/apt/incoming
allow_dcut= 1
post_upload_command = ssh /srv/apt/script/ && sudo apt-get update

Source code


set -u
set -e
set -x


sudo apt-get -y build-dep "$pkg" 
curver=`(apt-cache show $pkg || echo 'Version: 0~0') | awk '/Version:/ {print $2}'`

tmpdir=`mktemp -d "/var/tmp/pkg-${pkg}-XXXXXXX"`

cd "$tmpdir" 
apt-get source "$pkg" 
pkgdir=`find * -maxdepth 0 -type d | head -n 1`
echo "*** building in $pkgdir ***" 
cd "$pkgdir" 

dch --l '+dyson' 'Package for Dyson'
while true; do
    newver=`dpkg-parsechangelog | awk '/Version:/ {print $2}'`
    if dpkg --compare-versions "$newver" gt "$curver"; then
        if [ $bump = 0 ]; then
            echo "There is already package version $newver in Dyson. Bump version? [y/N]" 
            read bump
        case $bump in
            dch -i ''
            vertries=`expr $vertries - 1 || true`
            if [ $vertries = 0 ]; then
                echo "Version bump failed!" 
                exit 1
            echo "Aborted" >&2
            exit 1

EDITOR=true dch -r --no-force-save-on-release
dpkg-buildpackage -sa
dput dyson `realpath ../*.changes`

rm -fr -- "$tmpdir" 

exit 0

Sustaining ported Debian packages

If Debian packages needs more attention than a simple patch to upstream sources, they need to be ported, and changes should be tracked in Git. After experimenting some time the best approach has been found.

What's wrong with Debian VCS repositories

1. Some Debian packages aren't tracked in Git at all. Subversion, Bazaar are still quite popular. This affects essential and the most hard to port and maintain packages like Binutils, GCC, OpenJDK, etc.
2. Debian repositories can stale, that is new packages are uploaded to APT repositories, but VCS repositories aren't updated. It is especially painful when a new version is required to fulfill build dependencies.
3. Most of Debian's Git repositories are bloated with upstream sources, pristine tarballs, branches, etc. We don't need them all. It all needs a lot of storage.

Dyson's approach

As some of Debian packages do, we should track only the ./debian directory without upstream sources or tarballs. After all, we take them from Debian. We completely ignore Debian's VCS be it Git, Subversion or Bazaar. Instead
we start a git repository by importing the ./debian directory of some Debian version, and then we make and track our changes in the master branch. Vanilla Debian's version is tracked in the debian branch. When a new version
lands in Debian and need to be ported, we import it into the debian branch first (with no conflicts, etc.) and then merge the debian branch into the master branch, resolve conflicts, update Dyson specific parts etc.

See for example Binutils


The .git directory is not friendly to dpkg format version 1.0. It can be moved away before building packages or dpkg-source can be told to ignore it.