Prime / Optimus laptops and multi GPU systems

I’ve seen around tons of confusion about Optimus laptops, Prime and systems with multiple GPUs (like a desktop with an Nvidia dedicated GPU and an embedded AMD GPU) and how to configure them. People get mad with variables, scripts and extra tools.

The truth is, there’s not much to configure and since a few years, for most common cases, everything works out of the box.

Let’s take into consideration a very common case, a laptop with Intel + Nvidia GPU (Dell Precision 5680, Nvidia Optimus):

$ lspci | grep -i vga
00:02.0 VGA compatible controller: Intel Corporation Raptor Lake-P [Iris Xe Graphics] (rev 04)
01:00.0 VGA compatible controller: NVIDIA Corporation AD104GLM [RTX 3500 Ada Generation Laptop GPU] (rev a1)

And then let’s take the two most common cases into consideration to drive the GPUs.

  • Intel + Nouveau open source driver (DRI/DRI)
  • Intel open source driver + Nvidia proprietary driver (DRI/NVIDIA)

Power management

The system boots with the graphical output driven by the integrated Intel GPU (00:02.0) and the Nvidia GPU (01:00.0) is off.

$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
suspended

A simple command that touches the PCI card like lspci or nvidia-settings is enough to wake up the Nvidia GPU for probing:

$ lspci > /dev/null 
$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
active

A few seconds after, the GPU is again in suspended:

$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
suspended

The transition is always fast if no program is using the GPU, it usually takes just 4 or 5 seconds for the GPU to turn off. For example after exiting a game, you hear immediately the fan shutting down when the GPU goes off.

This is the simplest way to check power state of the GPU both when using the open source Nouveau driver and the Nvidia proprietary driver.

VGA Switcheroo (DRM drivers only)

If you are using the open source driver, there are a few added benefits in terms of control. The VGA Switcheroo files appear as soon as two GPU drivers and one handler have registered with vga_switcheroo.  since multiple GPUs are using a common framework, vga_switcheroo is enabled and we we can manipulate the state of the devices:

$ sudo cat /sys/kernel/debug/vgaswitcheroo/switch
0:IGD:+:Pwr:0000:00:02.0
1:DIS-Audio: :DynOff:0000:01:00.1
2:DIS: :DynOff:0000:01:00.0

After firing up the GPU for a workload, we can see the state reflected into the virtual file:

$ sudo cat /sys/kernel/debug/vgaswitcheroo/switch
0:IGD:+:Pwr:0000:00:02.0
1:DIS-Audio: :DynOff:0000:01:00.1
2:DIS: :DynPwr:0000:01:00.0

The DIS-Audio device is the actual HDA sound card on the GPU that is used to send output to an external output (ex. HDMI). That is also controlled by the dynamic control of the devices.

The configuration is flexible, so for example you could have two or more discrete GPUs and one extra audio controller for an eventual HDMI port.

You can also do some really lowlevel stuff, like this one to switch the display output to the discrete GPU if you have an old system with disconnected GPUs that uses a MUX to switch the display output:

$ sudo echo MDIS > /sys/kernel/debug/vgaswitcheroo/switch

Selecting the GPU to use when running a program from the desktop

If running on Gnome or KDE, any application can be selected to run on the discrete GPU directly from the desktop by right clicking on the icon:

This is supported both in the case of multiple DRI/DRM devices and or a combination with Nvidia proprietary drivers. There is no visible difference between the two.

Both Gnome and KDE feature an extra setting that can be added to desktop menus to prefer the integrated GPU. For example Steam provides this by default:

$ cat /usr/share/applications/steam.desktop | grep -i GPU
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true

Applications bearing those entries receive the opposite treatment, they run by default on the discrete GPU and by right clicking we can select the internal GPU:

Selecting the GPU to use with switcherooctl

The system comes with a userspace utility to manipulate the GPUs and that also prints the variables you can use to address a specific GPU. Prime / VGA Swicheroo case:

$ switcherooctl list
Device: 0
  Name:        Intel Corporation Raptor Lake-P [Iris Xe Graphics]
  Default:     yes
  Environment: DRI_PRIME=pci-0000_00_02_0

Device: 1
  Name:        NVIDIA Corporation AD104GLM [RTX 3500 Ada Generation Laptop GPU]
  Default:     no
  Environment: DRI_PRIME=pci-0000_01_00_0

The DRI_PRIME variable is never set by default and it’s assumed to be at 0 (so main integrated GPU in most cases) if nothing else sets it.

In the case of Nvidia proprietary drivers, the tool is smart enough to set the appropriate Nvidia variables to achieve the same result:

$ switcherooctl list
Device: 0
  Name:        Intel Corporation Raptor Lake-P [Iris Xe Graphics]
  Default:     yes
  Environment: DRI_PRIME=pci-0000_00_02_0

Device: 1
  Name:        NVIDIA Corporation AD104GLM [RTX 3500 Ada Generation Laptop GPU]
  Default:     no
  Environment: __GLX_VENDOR_LIBRARY_NAME=nvidia __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only

Think of switcherooctl as a replacement for setting up variables. For example, if your system has 4 GPUs and you want to target the 4th GPU, these commands are equivalent:

$ switcherooctl launch -g 3 <command>
$ DRI_PRIME=3 <command>
$ DRI_PRIME=pci-0000_03_00_0 <command>

Selecting the GPU to use with environment variables

OpenGL context

OpenGL came in before this multiple GPU – multiple GPU vendor thing existed, so by default, the first used GPU is the one used to run OpenGL applications in the main display and leave the second GPU off:

$ glxinfo -B | grep string
OpenGL vendor string: Intel
OpenGL renderer string: Mesa Intel(R) Graphics (RPL-P)
OpenGL core profile version string: 4.6 (Core Profile) Mesa 24.0.8
OpenGL core profile shading language version string: 4.60
OpenGL version string: 4.6 (Compatibility Profile) Mesa 24.0.8
OpenGL shading language version string: 4.60
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 24.0.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
suspended

In the case of the Intel + Nvidia proprietary drivers, we can use the Nvidia variables consumed by the proprietary driver to select the GPU and let the system power on the extra GPU:

$ __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo -B | grep string
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA RTX 3500 Ada Generation Laptop GPU/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 555.42.02
OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL version string: 4.6.0 NVIDIA 555.42.02
OpenGL shading language version string: 4.60 NVIDIA
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 555.42.02
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
active

If we are using open source drivers for both Intel + Nvidia (Nouveau), we can use the Mesa DRI variables to select the GPU:

$ DRI_PRIME=1 glxinfo -B | grep string
OpenGL vendor string: Mesa
OpenGL renderer string: NV194
OpenGL core profile version string: 4.3 (Core Profile) Mesa 24.0.8
OpenGL core profile shading language version string: 4.30
OpenGL version string: 4.3 (Compatibility Profile) Mesa 24.0.8
OpenGL shading language version string: 4.30
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 24.0.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20

We can now use both ways of checking the power state of the GPUs via the PCI devices or with VGA Switcheroo:

$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
active
$ sudo cat /sys/kernel/debug/vgaswitcheroo/switch
0:IGD:+:Pwr:0000:00:02.0
1:DIS-Audio: :DynOff:0000:01:00.1
2:DIS: :DynPwr:0000:01:00.0

VA-API (Video Acceleration API) context

$ vainfo | grep version
libva info: VA-API version 1.21.0
libva info: Trying to open /usr/lib64/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_21
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.21 (libva 2.21.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 24.2.3 (Full Feature Build)
$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
suspended

VA-API has its own set of variables for selecting which driver to use in the case of Intel + Nvidia proprietary drivers:

$ LIBVA_DRIVER_NAME=nvidia vainfo | grep version
libva info: VA-API version 1.21.0
libva info: User environment variable requested driver 'nvidia'
libva info: Trying to open /usr/lib64/dri/nvidia_drv_video.so
libva info: Found init function __vaDriverInit_1_0
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.21 (libva 2.21.0)
vainfo: Driver version: VA-API NVDEC driver [direct backend]
$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
active

Again, with the open source stack, also the DRI variable or switcherooctl are required:

$ DRI_PRIME=1 LIBVA_DRIVER_NAME=nouveau vainfo | grep version
libva info: VA-API version 1.21.0
libva info: User environment variable requested driver 'nouveau'
libva info: Trying to open /usr/lib64/dri/nouveau_drv_video.so
libva info: Found init function __vaDriverInit_1_21
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.21 (libva 2.21.0)
vainfo: Driver version: Mesa Gallium driver 24.0.8 for NV194
$ cat /sys/bus/pci/devices/0000:{00:02.0,01:00.0}/power/runtime_status
active
active

VDPAU context

VDPAU is pretty much dead, there is no support for Optimus/Prime laptops and no support for Wayland.

Vulkan or EGL context

Vulkan and EGL were thought with this use case in mind and the selection of the GPU to use ties into the extensions, so usually the correct one is already considered by the program using the appropriate API. The program can query a particular extension to get an ordered list of GPUs or with some other mechanism. This is usually performed by the program itself, so there is not really a way to “force” one specific GPU.

For example, vkcube allows us to select the GPU:

$ vkcube --gpu_number 0 --c 20
Selected GPU 0: Intel(R) Graphics (RPL-P), type: IntegratedGpu
$ vkcube --gpu_number 1 --c 20
Selected GPU 1: NVIDIA RTX 3500 Ada Generation Laptop GPU, type: DiscreteGpu

Contrary to the OpenGL context, you can check with the following commands that there is always a list of GPUs to use and never a single GPU information:

$ eglinfo -B
$ __NV_PRIME_RENDER_OFFLOAD=1 eglinfo -B
$ vulkaninfo --summary

There are some variables or programs that can be used to influence the extensions used for querying the GPUs, but it’s not really a supported path. The application decides based on the information provided by the drivers and some predefined criteria.

Forcing the usage of X on a specific GPU in a Wayland context

Everything described so far is applied as well to Wayland. On top of that, Xwayland is started whenever an application that does not support Wayland yet is started in a Wayland desktop.

If you want to force the use of Xwayland for a program that supports both Wayland and X, then you just need to set an additional variable.

For example, depending on the context (DRI, Nvidia, etc), these are all equivalent:

$ XDG_SESSION_TYPE=X11 __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxgears
$ XDG_SESSION_TYPE=X11 DRI_PRIME=1 glxgears
$ XDG_SESSION_TYPE=X11 switcherooctl launch -g 1 glxgears

CentOS 7.4 package rebases

As many have requested, I’ve enabled the updates for CentOS 7.4. As of this very moment, you need to enable the Continuous Release repository, which will get emptied when the final CentOS 7.4 images will be released. This means all the temporary packages I’ve put in the Red Hat Enterprise Linux 7.4 repository are now mainline.

If you are on CentOS 7.3 please proceed as follows:

# yum clean all
# yum-config-manager --enable cr
# yum update

You can then disable the cr repository (if you want) once CentOS 7.4 is out.

If you are on RHEL 7.4, you need to remove the temporary repository:

# yum clean all
# rm -f /etc/yum.repos.d/rhel74-temp.repo
# yum update

All Gstreamer packages are now at 1.10 as well as some other updates that have been already pushed into the Fedora repositories, like x265, HandBrake, etc..

RHEL 7.4 multimedia packages and Skype repository removal

The upgrade path from Red Hat Enterprise Linux 7.3 to 7.4 is a bit of a pain if you have the multimedia repository configured. This is because I’m rebuilding a few components for an upgraded libwebp package and because a lot of stuff has been rebased to versions that are in Fedora. Judging by the logs, I see that most of the downloads come from CentOS systems, so I just decided to hold on some updates that are required for the various package rebases for Red Hat Enterprise Linux 7.4. So until also CentOS releases version 7.4, I can’t make everyone happy and something (like Gstreamer plugin updates) will be stuck with 7.3 versions. Hopefully the new CentOS release will come quickly enough.

Also, I decided to stop rebuilding the base packages to use a newer libwebp version. This really had very few benefits and just a lot of pain due to the huge amount of packages involved in both x86_64 and i686 variants. The amount of packages affected by this weigh at around 3 gb.

In RHEL 7.4 there are additional WebKit variants that also would require a rebuild. So, as of today, to update the packages from the EPEL 7 multimedia repository you should run this command:

rpm -e --nodeps GraphicsMagick && yum distro-sync && yum -y install GraphicsMagick

Hopefully you would get an output similar to this:

Dependencies Resolved

==============================================================================================
 Package                         Arch        Version                  Repository         Size
==============================================================================================
Updating:
 compat-ffmpeg-libs              x86_64      1:2.8.12-2.el7           epel-multimedia   5.6 M
 ffmpeg                          x86_64      1:3.3.3-2.el7            epel-multimedia   1.5 M
 ffmpeg-libs                     i686        1:3.3.3-2.el7            epel-multimedia   6.1 M
 ffmpeg-libs                     x86_64      1:3.3.3-2.el7            epel-multimedia   6.3 M
 gstreamer1-plugins-bad          x86_64      1:1.4.5-5.el7            epel-multimedia   1.8 M
 libavdevice                     x86_64      1:3.3.3-2.el7            epel-multimedia    63 k
Downgrading:
 leptonica                       i686        1.72-2.el7               epel-multimedia   881 k
 leptonica                       x86_64      1.72-2.el7               epel              928 k
 libwebp                         i686        0.3.0-3.el7              base              169 k
 libwebp                         x86_64      0.3.0-3.el7              base              170 k
 lz4                             x86_64      1.7.3-1.el7              epel               82 k
 python-pillow                   x86_64      2.0.0-19.gitd1c6db8.el7  base              438 k
 webkitgtk                       x86_64      2.4.9-1.el7              epel               12 M
 webkitgtk3                      x86_64      2.4.9-6.el7              base               11 M
Installing for dependencies:
 libwebp0.6                      i686        0.6.0-1.el7              epel-multimedia   255 k
 libwebp0.6                      x86_64      0.6.0-1.el7              epel-multimedia   250 k

Transaction Summary
==============================================================================================
Install               ( 2 Dependent packages)
Upgrade    6 Packages
Downgrade  8 Packages

Total download size: 47 M
Is this ok [y/d/N]:

Basically libwebp should come again from the main CentOS/RHEL channels and the libwebp0.6 package should come from the multimedia repository. All the packages which were rebuilt for the previous libwebp 0.5 update should become synced again to their proper versions.

If you don’t get this output, but still get some dependency errors you have to do some debugging. For example, ffmpeg-libs.i686 requires libssh.i686, but the version of libssh in CentOS extras is different from the one in EPEL (it really depends on what kind of packages you have installed and with which repositories enabled) so I’m providing here the same version that is in CentOS extras but in both variants.

Update 16th August 2017

If you get many qt5 errors during the transactions, keep in mind that RHEL 7.4 has been rebased massively, and everyone else (including EPEL) is catching up. As of today, if you have the following errors (trimmed down) in a Yum transaction:

Error: Package: gvfs-1.30.4-3.el7.x86_64 (rhel-x86_64-server-7)
Error: Package: qt5-qtwebkit-5.6.1-3.b889f46git.el7.x86_64 (epel)
Error: Package: qt5-qtquickcontrols2-5.6.1-2.el7.x86_64 (@epel)
Error: Package: qt5-qtquickcontrols2-5.6.1-2.el7.x86_64 (@epel)
Error: Package: GraphicsMagick-1.3.26-3.el7.x86_64 (@epel-multimedia)
Error: Package: kf5-kdeclarative-5.36.0-1.el7.x86_64 (epel)
Error: Package: qt5-qtquickcontrols2-5.6.1-2.el7.x86_64 (@epel)
Error: Package: qt5-qtwebkit-5.6.1-3.b889f46git.el7.x86_64 (epel)
Transaction check error:
  file /usr/lib64/gstreamer-1.0/libgstopus.so from install of gstreamer1-plugins-bad-1:1.4.5-5.el7.x86_64 conflicts with file from package gstreamer1-plugins-base-1.10.4-1.el7.x86_64

You can do the following. For this:

Error: Package: GraphicsMagick-1.3.26-3.el7.x86_64 (@epel-multimedia)

Do:

rpm -e --nodeps GraphicsMagick && yum -y install GraphicsMagick

All of the QT7KDE 5 stuff:

Error: Package: qt5-qtwebkit-5.6.1-3.b889f46git.el7.x86_64 (epel)
Error: Package: qt5-qtquickcontrols2-5.6.1-2.el7.x86_64 (@epel)
Error: Package: qt5-qtquickcontrols2-5.6.1-2.el7.x86_64 (@epel)
Error: Package: kf5-kdeclarative-5.36.0-1.el7.x86_64 (epel)

Are in EPEL testing updates, so:

yum --enablerepo=epel-testing update

These:

Error: Package: gvfs-1.30.4-3.el7.x86_64 (rhel-x86_64-server-7)Transaction check error:
  file /usr/lib64/gstreamer-1.0/libgstopus.so from install of gstreamer1-plugins-bad-1:1.4.5-5.el7.x86_64 conflicts with file from package gstreamer1-plugins-base-1.10.4-1.el7.x86_64

are some of the packages that are rebased in RHEL 7.4. I’ve created a temporary repository for those, it will disappear once CentOS 7.4 is released as the packages will be integrated in the main multimedia repository. You can install it through:

yum-config-manager \
  --add-repo=https://negativo17.org/repos/rhel74-temp/rhel74-temp.repo

With the above repository it is possible to install all the other multimedia packages.

Skype repository removal

Skype 4.3 is 32 bit only, is now obsolete and has been superseded by a package that actually lists proper dependencies. It is also one of the packages that required one of the above WebKit rebuilds in i686 form for RHEL/CentOS 7 x86_64.

If you have it installed, just remove it with:

yum remove webkitgtk.i686

The repository has been deleted; to install the new Skype provided version, just head to the following official link.

Fedora 24 and CentOS/RHEL 7 repositories

Fedora 24 repositories have been available for quite some time now, but here is the official statement that everything should be supported out of the box.

As part of the repository availability, I would like to say that starting from Fedora 24, the repositories are self-sustained and do not require RPMFusion to be enabled. I try to preserve compatibility between the two, so if you step into any problem just open an issue to the specific package on Github, send me an email or drop a message in the comment section of the various pages. Please note that “compatible” means that actually you shouldn’t get any conflict when installing packages, and not that I will not overwrite/obsolete the packages provided in the other repositories.

CentOS/RHEL 7 repositories have been available stand alone since the beginning and do not require external repositories to be enabled. Again, if an RPMFusion (or whatever will be mainstream at the moment) CentOS/RHEL 7 repository will appear, I will try to be compatible with it.

Scope of support

My basic idea is to have what I’m using normally everyday as a package in Fedora, enabling software combinations that would be otherwise impossible to distribute in official repositories due to license/patent issues. This for example includes NVENC (Nvidia Encoder) FFMPeg enabled builds that I use almost everyday.

Being a daily CentOS/RHEL 7 user I also want to support the latest and gretest of the same software on that platform, which also means rebuilding some official CentOS/RHEL 7 packages like VP8/9, VDPAU and VA-API libraries.

Due to the various package builds being different (or simply containing newer software releases) from what the other repositories offer, I also try to be completely independent, you can basically install the operating system and just use my repositories.

Build system changes

The (internal at the moment) build system uses Github as its primary system for storing the package information. There is a Negativo17.org public organization where all the work goes, so if you want to look at the development or the SPEC files, just browse to Github. If you have an issue or proposed change as well, you’re welcome to open an issue or create a merge request in the specific package Git page.

Skype Web Pidgin plugin

skype

The Skype repository used to contain purple-skype for Fedora and CentOS/RHEL distributions which at the time required an installed Skype to work. Now, I helped a new Fedora contributor into integrating the newly developed Skype web plugin, which is based on the Skype web client. The package in Fedora obsoletes and provides correctly the skype4pidgin plugin and as such I don’t need to provide anything else in the repository.

The installation instructions have been updated to reflect this.

Skype is available only in 32 bit format, so on a 64 bit a 32 bit client will always be installed. Since the merging with MSN, the HTML welcome screen requires a 32 bit WebKit GTK build to start. This is not included in the 64 bit only CentOS/RHEL 7 repositories; so for this reason, if you are running CentOS/RHEL 7, it requires the multimedia repository to be enabled and have the dependency solved. This used to be self-contained in the Skype repository, but this is no longer feasible for me to mantain considering there is a different rebuild of WebKit GTK in the Multimedia repository.

Spotify Client

spotify-client

The Spotify repository used to contain FFMpeg for CentOS/RHEL distributions and a requirement on FFMpeg’s RPMFusion as a Fedora dependency. FFMpeg is no longer included in the CentOS/RHEL 7 repositories so the multimedia repository has to be enabled to have the dependency solved. As for Skype, this no longer feasible for me to mantain considering there is a different rebuild of WebKit GTK in the Multimedia repository.

Here as well the installation instructions have been updated to reflect the change.

aKMOD kernel module packages

The kernel binary module packages generated by aKMOD are now compressed with XZ, like in the original Fedora kernel packages that contain kernel modules. I’ve become a DKMS contributor, so, as time permits, I will add the same functionality to DKMS for Fedora distributions.

At the moment, this applies to Nvidia and X-Pad kernel modules.

Gstreamer plugins and multimedia libraries

The Multimedia repository now provides GStreamer (1.0) plugins for Bad, Ugly, libAV and VA-API plugin bundles with all options enabled. This is split into the following GStreamer runtime packages:

  • gstreamer1-plugins-bad
  • gstreamer1-plugins-ugly
  • gstreamer1-vaapi
  • gstreamer1-libav
  • gstreamer1-plugins-bad-fluidsynth (pulls in the whole FluidSynth distribution)
  • gstreamer1-plugins-bad-nvenc (x86_64 only, pulls in the Nvidia binary driver; and at the moment it does not work properly)

They all have an Epoch of “1”, due to the various reasons explained at the top. They are not yet available for CentOS/RHEL 7 due to time constraints; I will try to prepare them in the next weeks.

Fedora 24 OpenH264 repository

A note on the Fedora 24 OpenH264 repository. As described in its wiki page, there is an extra repository that can be enabled directly in Fedora 24 that allows you to install OpenH264, its relevant Gstreamer 1.0 plugin and a Mozilla plugin for Firefox. Following the same logic, at the moment the same Gstreamer 1.0 plugin is provided/obsoleted (in newer form) by the gstreamer1-pluings-bad package. There is a conflict for the OpenH264 binaries which I will address soon.

Updated packages and new Samsung repository

As some of you may have noticed, a lot of updates and new stuff has been pushed.

Highlights from the updates

  • The Nvidia driver version 358.16 has been promoted as “Short Lived” for Fedora, and it has support for X.org Video ABI 20. So it is now the default for Fedora 21, 22 and 23.
  • Driver version 352.63 is the new “Long Lived” driver for RedHat/CentOS.
  • Both drivers have a fallback mechanism for the SELinux regression introduced in 358.09, so you don’t need anymore to disable SELinux for GDM refresh problems.
  • The legacy driver has been updated to 340.96, and this as well has been enabled for Fedora 23 as it also supports X.org 1.18
  • CDRtools after years of an alpha 3.01 has finally updated to… an alpha 3.02 😀
  • HandBrake has been updated to the very latest snapshot and is relying only on separate source tarballs that are not statically linked. Unfortunately some are of dubious licenses as usual. Please note that there are some issues with subtitle tracks embedded in Matroska files not being correctly interpreted.
  • The Nvidia NVML library and CUDA packages have seen some small update.
  • Steam has been updated to version 1.0.0.51 and has updated UDev rules for the Steam Controller. If you are one of the owners of such controller, you will find support out of the box. The same changes have also been pushed to the RPMFusion package.

New repository

There’s a new repository for Samsung printers, multifunction printers and scanners that carries the “Samsung Unified Linux Driver” for both the scanning and printing functions. Just by installing it and enabling the ports in the firewall should be enough to get every device running in no time. Refer to the appropriate page for details.

Fully fledged FFMpeg binaries

Also, due to popular request, there is now a custom built FFMpeg package that drops in as a replacement for RPMFusion ones and that enables linking and support for all the codecs/encoders/decoders that would result in an unredistributable binary. This is now available the HandBrake repository. The following codecs/encoders/decoders/transports have been enabled:

  • VP8 and VP9 de/encoding
  • WebP encoding
  • AAC (Fraunhofer, LibVO and other variants) de/encoding
  • OpenAL 1.1 capture support
  • BluRay reading
  • AMR-WB de/encoding
  • AMR-NB de/encoding
  • RTMP[E] support
  • H.264 encoding (OpenH264, Cisco variant)
  • OpenGL rendering
  • SSH transport
  • Fontconfig/fribidi text support

This sobstitutes the ffmpeg binary that was provided as part of the CUDA enabled programs, as it is now tied to all the other multimedia libraries available in this repository. The support for Nvidia H.264/H.265 hardware encoding/decoding is enabled here as well and the required packages are now installed through the use of RPM weak dependencies.

The package has a different Epoch so it is not overwritten by normal updates. The idea is to have all the possible codecs supported out of the box, so also expect HEVC kvazaar (H.265), Intel Quick Sync Video (H.265) hardware support through libmfx/mfx_dispatch, CIFS transport, and other stuff, as soon as I have more time.

The same repository will be used to host the CUDA and FFMpeg enabled Blender, as it makes no sense to have a separate repository for it. Either you have a full blown multimedia collection with each component strictly tied to each other, or you just have the plain Fedora repositories with no license/patent encumbered options.

Enjoy!

BluRay playback and ripping on Fedora (AACS, BD+, BD-J)

There are multiple ways that one can try to make BluRay decryption and playback in Linux. Of course, after some googling and fiddling around, you can see that is quite simple even if not the different instructions are quite confused as they span across multiple iterations of software development.

First of all a brief introduction. It is all explained here in great detail on the BluRay Wikipedia page, this is just an extract.

There are two different types of encryption:

  • AACS, performed using keys)
  • BD+, performed using a small embedded Java VM that executes programs and decrypts contents

And one type of “enhanced” java embedded menu (even small apps, like internet connected browsers, etc.) that can run on the BluRay player:

  • BD-J, using a GEM standard Java VM that includes also BDlive, for internet access

If any of these is implemented in a disk you own, the thing you need to do is simply insert a disk and run the bd_info command (from the libbluray-utils package) against your BD/DVD device.

Screenshot from 2015-08-27 10-59-57

This, of course, does work if you have the proper decryption keys or software installed on your system. That is, by default, nothing. 🙂

So, to enable decryption of the discs, you can proceed in two different ways, one using only open source software (not really, as you need anyway keys and a JVM dump of a BluRay Player) or going through commercial software (free at the moment while in beta).

Unfortunately none of my BluRays worked with open source tools on my system. I was not even able to get the required keys with the aacskeys program; so the proprietary software is my current choice.

Required repositories

In both cases, first of all enable the RPMFusion and the HandBrake/MakeMKV repository. Most of the keys required can be fetched from labDV, where you can also contribute back yours.

For the following examples I’m taking VideoLan as the main player, as it has good support (and a nice interface) to fiddle around with the various settings and is already available in RPMFusion.

Open Source AACS/BD+ decryption

First of all install libaacs and libbdplus from RPMFusion:

dnf install libaacs libbdplus

Then put the required AACS keys in a place, so that your AACS client can find them. For example:

mkdir -p ~/.config/aacs
wget -c http://www.labdv.com/aacs/KEYDB.cfg -O ~/.config/aacs/KEYDB.cfg

Now, VLC, using libbluray, should dynamically load the library if it finds it on the system and then decrypt the AACS protected content if the key for the specific disc is available.

Similar to AACS, put the required BD+ JVM dump in the appropriate folder, so that your BD+ client can find them. For example:

mkdir -p ~/.config/bdplus/
wget -c http://www.labdv.com/aacs/libbdplus/bdplus-vm0.bz2 -O ~/bdplus-vm0.bz2
tar -xvjf ~/bdplus-vm0.bz2 -C ~/.config/

Again, now libbluray should dynamically load the library if it finds it on the system and then decrypt the BD+ protected content using the VM dump in your personal folder.

Do not forget to update the AACS keys and the VM dump every once in a while!

Moving keys and dumps in a system wide location

This is required if you have multiple user for the system and you want to avoid each user into maintaining its own set of keys and dumps.
After installing everything in your personal folder, you will end up with a structure like the following:

$ find .config/bdplus .config/aacs | sort
.config/aacs
.config/aacs/KEYDB.cfg
.config/bdplus
.config/bdplus/vm0
.config/bdplus/vm0/aes_keys.bin
.config/bdplus/vm0/device_discovery_1.bin
.config/bdplus/vm0/device_discovery_2.bin
.config/bdplus/vm0/device_discovery_3.bin
.config/bdplus/vm0/device_discovery_4.bin
.config/bdplus/vm0/device_discovery_5.bin
.config/bdplus/vm0/ecdsa_keys.txt
.config/bdplus/vm0/mem_area_02.bin
.config/bdplus/vm0/mem_area_03.bin
.config/bdplus/vm0/mem_area_04.bin
.config/bdplus/vm0/mem_area_05.bin
.config/bdplus/vm0/mem_area_06.bin
.config/bdplus/vm0/mem_area_07.bin
.config/bdplus/vm0/mem_free.bin
.config/bdplus/vm0/memory.map
.config/bdplus/vm0/mem_player_executable.bin
.config/bdplus/vm0/mem_player_name.bin
.config/bdplus/vm0/mem_player_version.bin

To move up everything to a common location, just performs the following commands:

sudo mv ~/.config/{aacs,bdplus} /etc/xdg
sudo chown -R root:root /etc/xdg/{aacs,bdplus}

That’s it!

Proprietary AACS/BD+ decryption

This is done through MakeMKV, available from the HandBrake/MakeMKV repository, with the registration key available publicly from their forum. The software is fast, works really well, and although not open source is the only way to properly get access to your disks.

Support for external decoders has been added in libbluray some time ago, and allows you to specify different libraries than libaacs/libbdplus for decrypting content.

To proceed, remove the libaacs/libbdplus libraries if you have them installed, and install MakeMKV:

dnf remove libaacs libbdplus
dnf install libbdplus

As explained in the repository page, the MakeMKV package sets up environment variables that override the default libraries using for decryption and just uses MakeMKV’s libmmbd to launch a hidden MakeMKV instance for decryption in the background. To load the environment, logoff and login again, so it is picked up by any program starting.

After logging in, check that the environment is loaded with the following command:

$ env | egrep "LIBAACS_PATH|LIBBDPLUS_PATH"
LIBBDPLUS_PATH=/usr/lib64/libmmbd.so.0
LIBAACS_PATH=/usr/lib64/libmmbd.so.0

Then start VLC, select to open a BluRay disc, with or without the menus. Both will smoothly work as long as it is not a BD-J, as you can see in the pictures below. Menu is navigable, reactive to selections and clickable.

menus

Now also the command bd_info works fine, using the same mechanism.

BD-J Java menus

BD-J support is still in its infancy, at the moment of writing, with the latest libbluray 0.8.1 I am able to get part of the menus working. Most of the time I just got a video loop where the menu should be but not the actual menu. This is much better than having just VideoLan crashing, though. 🙂

Support for this is enabled by installing the libbluray-bdj package. The package puts an OpenJDK compiled Java Archive inside the classpath of the Java VM, so no further configuration is required. To install the package, just do:

dnf install libbluray-bdj

After this, in VideoLan you can just select “Open Disc”, “Blu-Ray” as the source and deselect “No disc menus”. As I said, support is not perfect, in the screnshot below I was able to see the menus but not click on them and in the background I was having a lot of errors.

bdj

I’m tracking the upstream project, so if the library can be rebuilt without breaking compatibility with the additional Fedora packages, I will add it to the repository along with MakeMKV. Before version 0.8.1 I was not even able to open a BD-J enabled BluRay disc with VideoLan.

One final curiosity

All my BD-J enabled discs have a Playstation 3 firmware update on the disc. Don’t know why, but probably because Sony owns the BluRay format so they can do as they please. Meh!

As always, feedback is welcome.

Steam for CentOS / RHEL 7

The Steam repository now contains the Steam client package plus the S3 texture compression library for Open Source drivers for CentOS and Red Hat Enterprise Linux 7.

The CentOS/RHEL repository contains also all the SteamOS session files and binaries for running a Steam-only system, like the Fedora ones. As the Fedora packages, the main client is 32 bit only, so when running on 64 bit systems, make sure to load also your 32 bit libraries if you are running on proprietary drivers or the S3 texture compression library if you are running on a 64 bit system. Work on Valve’s X-Box kernel module for CentOS/RHEL is ongoing; as in its current form there are unresolved symbols.

As part of the update, also the Fedora X-Box kernel module has additional fixes on top of Valve’s code.

I will also add the packages to RPMFusion when a CentOS/RHEL 7 branch will eventually be available.

For full details see the repository page.

centos-steam2

centos-steam3

Converting system between RHEL and CentOS

rhel2centosHave you ever had the need to switch a CentOS system to a valid Red Hat Enterprise Linux subscription and viceversa?

I had this need quite a few times, with the most simple case being to transform an evaluation environment based on CentOS that has been used to convince a boss, into a fully supported Red Hat subscription at the end of the evaluation.

On the other hand, it could prove very useful to create an exact copy of an installed system that is currently attached to a Red Hat subscription on an image in your laptop for development purposes. Or simply because the Red Hat subscription has expired and we don’t need any kind of paid support from Red Hat.

As an example for this conversion tutorial, we’re using a CentOS/RHEL 6.6 system. The procedure is the same even if we are also switching minor release during the conversion; for example upgrading from 6.3 to 6.6.

From Red Hat Enterprise Linux to CentOS

This is the most simple case, mainly for two reasons. First of all, we can fetch the packages we need for the installation on the web (we don’t need a valid Red Hat subscription) and basically we are reducing the number of packages that are installed on the sytem in comparison with a pristine Red Hat Enterprise Linux system.

As the first step we must remove the -release package from the system and switch it with the one we’re interested in. This way the yum commands will be able to expand the necessary variables and fetch the correct packages.

rpm -e --nodeps redhat-release-server-6Server
yum -y install http://mirror.centos.org/centos/6/os/x86_64/Packages/centos-release-6-6.el6.centos.12.2.x86_64.rpm

Also, with CentOS and Fedora, the package that defines the system release contains also the yum repository definitions, speeding up conversion considerably.

Now, the only thing we need to do is to start the package syncing process. Yum will take care of the rest.

yum -y distro-sync
reboot

If during the upgrade we performed quite a significant jump of release (for example from 6.3 to 6.6) it’s good practice to also reset the SELinux contexts on the filesystem during the first reboot:

fixfiles onboot

System cleanup after the conversion

Before restarting the system, we can also take care of a few simple finishing touches; for example we can remove the Red Hat network support packages that we will never use again:

yum -y remove rhn\* subscription\* yum-rhn-plugin

Erase packages that are no longer available in any repository:

package-cleanup --orphans

Or we can also replace the initial Firefox starting page that suggests us to register our system with Red Hat Network:

rpm -e --nodeps redhat-indexhtml
yum -y install http://mirror.centos.org/centos-6/6.6/os/x86_64/Packages/centos-indexhtml-6-2.el6.centos.noarch.rpm

To remove the leftover kernels on the system (including packages containing kernel headers, modules, etc.) we can run this command that will clean the system for us from all kernels except the one we’re running:

package-clenup -y --oldkernels --count=1

From CentOS to Red Hat Enterprise Linux

The opposite procedure is slightly different. It’s a bit simpler as the commands we require to type are reduced (quite a few packages from CentOS keep providing the old Red Hat package name in the Provides: tags. It’s otherwise a bit longer as we need a valid account to download by hand the required packages for the conversion; as the yum repositories (or channels) are not available.

After getting access to the Red Hat customer portal, we need to download the following packages to register the system (in our example we’re targeting a Server subscription):

redhat-release-server
rhn-check
rhn-client-tools
rhn-setup
rhn-setup-gnome
rhnlib
rhnsd
subscription-manager
subscription-manager-firstboot
subscription-manager-gnome
yum-rhn-plugin

Now we can proceed with the system conversion, as yum will behave like running on a Red Hat system:

rpm -e --nodeps centos-release
yum install *rpm

Then we can register our host to the channels we want:

subscription-manager --register

And finally proceed with the package synchronization:

yum -y distro-sync
reboot

Samba 4 Active Directory with Bind DLZ zones, dynamic DNS updates, Windows static RPC

samba_logo_4cA guide on how to run a tightly secured Samba 4 based Active Directory Domain Controller to serve Windows 2000+ clients. This setup has the following advantages:

  • Static RPC ports, so you can have a firewall between your clients and Domain Controller
  • Bind DLZ zones (dynamic LDAP zones), that can be managed through standard Windows Remote Services Administration Tools
  • Dynamic DNS updates (clients register themselves in DNS)
  • No insecure LANMAN, NetBIOS, SMB1 enabled. Security is higher, performance is much better!

This makes the installation much hardened and secure than the default Microsoft setup.

This is an update to my old post for the new stuff that has changed during the past year and the introduction of CentOS/RHEL 7.

System enablement

This guide is written against Samba 4.x for Fedora and CentOS/RHEL 7 and a minimum Samba version of 4.1.6, as it’s the first Samba release that includes systemd support. You can grab the latest Samba source packages from Koji.

Both require a patched Samba package to enable the missing Domain Controller functionality. Hopefully this change will make it into official packages when Samba will be built with the system’s MIT Kerberos implementation.

The first patch is for disabling MIT Kerberos integration and enabling optional Heimdal Kerberos with Domain Controller functionality in the Redhat/Fedora package. This has also been reported upstream:

--- /dev/null
+++ b/samba-4.1.12-unit.patch
@@ -0,0 +1,12 @@
+diff -Naur samba-4.1.12.old/packaging/systemd/samba.service samba-4.1.12/packaging/systemd/samba.service
+--- samba-4.1.12.old/packaging/systemd/samba.service   2015-02-05 14:25:54.981110990 +0100
++++ samba-4.1.12/packaging/systemd/samba.service   2015-02-05 14:31:36.109654120 +0100
+@@ -8,7 +8,7 @@
+ PIDFile=/run/samba.pid
+ LimitNOFILE=16384
+ EnvironmentFile=-/etc/sysconfig/samba
+-ExecStart=/usr/sbin/samba $SAMBAOPTIONS
++ExecStart=/usr/sbin/samba -i $SAMBAOPTIONS
+ ExecReload=/usr/bin/kill -HUP $MAINPID
+ 
+ [Install]
diff --git a/samba.spec b/samba.spec
index 549e5d4..ee630e0 100644
--- a/samba.spec
+++ b/samba.spec
@@ -100,6 +100,7 @@ Source200: README.dc
 Source201: README.downgrade
 
 Patch0: samba-4.1.15-fix_auth_with_long_hostnames.patch
+Patch1: samba-4.1.12-unit.patch
 
 BuildRoot:      %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
@@ -255,6 +256,13 @@ Requires: %{name}-python = %{samba_depver}
 Provides: samba4-dc = %{samba_depver}
 Obsoletes: samba4-dc < %{samba_depver}
 
+%if %with_dc
+Requires: tdb-tools >= %{libtdb_version}
+Requires(post): systemd
+Requires(preun): systemd
+Requires(postun): systemd
+%endif
+
 %description dc
 The samba-dc package provides AD Domain Controller functionality
 
@@ -521,6 +529,7 @@ module necessary to communicate to the Winbind Daemon
 %setup -q -n samba-%{version}%{pre_release}
 
 %patch0 -p1 -b .samba-4.1.15-fix_auth_with_long_hostnames.patch
+%patch1 -p1
 
 %build
 %global _talloc_lib ,talloc,pytalloc,pytalloc-util
@@ -665,7 +674,7 @@ install -m 0644 %{SOURCE200} packaging/README.dc-libs
 %endif
 
 install -d -m 0755 %{buildroot}%{_unitdir}
-for i in nmb smb winbind ; do
+for i in nmb smb winbind %{?with_dc:samba}; do
     cat packaging/systemd/$i.service | sed -e 's@\[Service\]@[Service]\nEnvironment=KRB5CCNAME=FILE:/run/samba/krb5cc_samba@g' >tmp$i.service
     install -m 0644 tmp$i.service %{buildroot}%{_unitdir}/$i.service
 done
@@ -716,6 +725,15 @@ fi
 %post dc-libs -p /sbin/ldconfig
 
 %postun dc-libs -p /sbin/ldconfig
+
+%post dc
+%systemd_post samba.service
+
+%preun dc
+%systemd_preun samba.service
+
+%postun dc
+%systemd_postun_with_restart samba.service
 %endif # with_dc
 
 %post libs -p /sbin/ldconfig
@@ -1049,6 +1067,7 @@ rm -rf %{buildroot}
 %{_libdir}/mit_samba.so
 %{_libdir}/samba/auth/samba4.so
 %{_libdir}/samba/bind9/dlz_bind9.so
+%{_libdir}/samba/bind9/dlz_bind9_10.so
 %{_libdir}/samba/libheimntlm-samba4.so.1
 %{_libdir}/samba/libheimntlm-samba4.so.1.0.1
 %{_libdir}/samba/libkdc-samba4.so.2
@@ -1100,6 +1119,7 @@ rm -rf %{buildroot}
 %{_datadir}/samba/setup
 %{_mandir}/man8/samba.8*
 %{_mandir}/man8/samba-tool.8*
+%{_unitdir}/samba.service
 %else # with_dc
 %doc packaging/README.dc
 %exclude %{_mandir}/man8/samba.8*

Version change

Do not forget to bump the Epoch in the RPM spec file so packages do not conflict and are not overwritten by official packages with a lower epoch.

After patching, rebuild the packages with your favorite tools, rpmbuild, mock or koji, whatever your preference is.

Software installation

Install BIND server (required also for other optional domains), the NTP server, the Samba suite (the rpms you just rebuilt) and some additional tools used by our environment on the selected server. For servers; replace also firewalld with the base iptables service:

rpm -e firewalld
yum install iptables-services bind bind-utils ntp samba-dc samba-client tdb-tools \
    krb5-workstation policycoreutils-devel libselinux-utils cups
systemctl enable iptables
systemctl start cups
systemctl enable named
systemctl stop chronyd
systemctl disable chronyd
systemctl enable ntpd
systemctl enable samba

Networking

Disable IPv6

I had to disable IPv6 for my internal network, you might need to have it enabled. Do the following to permanently disable IPv6:

sysctl -w net.ipv6.conf.all.disable_ipv6=1
echo "net.ipv6.conf.all.disable_ipv6=1" >> /etc/sysctl.conf

Firewall configuration

The following ports need to be opened on the server firewall:

  • TCP: 53, 88, 135, 445, 464, 1024-5000
  • UDP: 53, 88, 123, 389, 464

Ports 1024-5000 are for the RPC services used by Samba, and can be further reduced in case you don’t have many clients. Port tcp/53 is used by Bind to receive DNS GSS record updates (they use TCP, not UDP). It is also used for large zone transfers, but this is not our case.

Create the file /etc/sysconfig/iptables and insert the following contents (we are assuming the server has an IP address of 192.168.0.17):

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp -d 192.168.0.17 --dport 53 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 53 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 88 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp -d 192.168.0.17 --dport 88 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp -d 192.168.0.17 --dport 123 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 135 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 389 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp -d 192.168.0.17 --dport 389 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 445 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 --dport 464 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp -d 192.168.0.17 --dport 464 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -d 192.168.0.17 -m multiport --ports 1024:5000 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Then start the firewall:

systemctl start iptables

Provisioning the domain

First setup and provisioning can be executed with SELinux disabled and then later re-enabled. This helps debugging issues that are not otherwise present with DAC permissions. Since the domain controller functionality has not been enabled yet in the official packages; SELinux policies have not been updated yet. Execute the following commands as root to start the provisioning:

setenforce 0
rm -f /etc/samba/smb.conf
samba-tool domain provision --dns-backend=BIND9_DLZ --realm=EXAMPLE.COM \
    --domain=EXAMPLE --server-role=dc --function-level=2008_R2 \
    --adminpass=Password01

Alternatively the provisioning command can be run without parameters and the installation will be interactive. An output like the following will be returned:

Looking up IPv4 addresses
Looking up IPv6 addresses
No IPv6 address will be assigned
Setting up secrets.ldb
Setting up the registry
Setting up the privileges database
Setting up idmap db
Setting up SAM db
Setting up sam.ldb partitions and settings
Setting up sam.ldb rootDSE
Pre-loading the Samba 4 and AD schema
Adding DomainDN: DC=example,DC=com
Adding configuration container
Setting up sam.ldb schema
Setting up sam.ldb configuration data
Setting up display specifiers
Modifying display specifiers
Adding users container
Modifying users container
Adding computers container
Modifying computers container
Setting up sam.ldb data
Setting up well known security principals
Setting up sam.ldb users and groups
Setting up self join
Adding DNS accounts
Creating CN=MicrosoftDNS,CN=System,DC=example,DC=com
Creating DomainDnsZones and ForestDnsZones partitions
Populating DomainDnsZones and ForestDnsZones partitions
See /var/lib/samba/private/named.conf for an example configuration include file for BIND
and /var/lib/samba/private/named.txt for further documentation required for secure DNS updates
Setting up sam.ldb rootDSE marking as synchronized
Fixing provision GUIDs
A Kerberos configuration suitable for Samba 4 has been generated at /var/lib/samba/private/krb5.conf
Once the above files are installed, your Samba4 server will be ready to use
Server Role:           active directory domain controller
Hostname:              samba
NetBIOS Domain:        EXAMPLE
DNS Domain:            example.com
DOMAIN SID:            S-1-5-21-1504993763-4098306314-3392174306

Disable NetBIOS

Edit the file /etc/samba/smb.conf and make sure that the [global] section contains the following lines (in addition to the others) to disable NetBIOS support:

[global]
    server services = -dns, -nbt
    smb ports = 445

When requesting a resource, Windows 2000 and later systems start two connections simultaneously to a server. One is on port 445 and one on port 139. If the client gets a response from port 445 it will reset (RST) the connection on port 139. If it only gets a response from port 139, that one is used. If you disable NBT (NetBIOS over TCP/IP) on your client; only port 445 is being tried. Pre-Windows 2000 clients (such as windows NT) only use port 139.

Configure Kerberos

Copy the provision generated Kerberos file to the default system location:

cp /var/lib/samba/private/krb5.conf /etc/krb5.conf

Make sure the Kerberos configuration file contains the check-ticket-addresses directive; as it is required for clients connecting through a NAT.

--- /etc/krb5.conf.old 2013-04-08 15:49:33.310944976 +0200
+++ /etc/krb5.conf  2013-04-08 15:49:57.989473099 +0200
@@ -2,3 +2,6 @@
    default_realm = EXAMPLE.COM
    dns_lookup_realm = false
    dns_lookup_kdc = true
+
+[kdc]
+   check-ticket-addresses = false

Configure NTP server

Change the NTP configuration file to enable Microsoft signed time queries:

--- /etc/ntp.conf.default  2013-08-09 10:10:07.362235547 +0200
+++ /etc/ntp.conf   2013-08-19 12:31:44.356572515 +0200
@@ -5,8 +5,8 @@

 # Permit time synchronization with our time source, but do not
 # permit the source to query or modify the service on this system.
-restrict default kod nomodify notrap nopeer noquery
-restrict -6 default kod nomodify notrap nopeer noquery
+restrict default kod nomodify notrap nopeer noquery mssntp
+restrict -6 default kod nomodify notrap nopeer noquery mssntp

 # Permit all access over the loopback interface.  This could
 # be tightened as well, but to do so would effect some of
@@ -51,3 +51,5 @@

 # Enable writing of statistics records.
 #statistics clockstats cryptostats loopstats peerstats
+
+ntpsigndsocket /var/lib/samba/ntp_signd/

Change permissions of the NTP folders which should be accessible by the daemon:

chgrp ntp /var/lib/samba/ntp_signd/

Configure DNS server

Look at the hints in the previous provisioning output regarding BIND and modify the file /etc/named.conf. Remember to fill appropriately the zone files with the correct records. Replace my addresses with yours, of course.

--- named.conf.rpmnew  2013-10-30 12:35:25.000000000 +0100
+++ named.conf  2014-02-11 10:19:13.361403985 +0100
@@ -8,29 +8,24 @@
 //

 options {
-   listen-on port 53 { 127.0.0.1; };
+   listen-on port 53 { 127.0.0.1; 192.168.0.17; };
    listen-on-v6 port 53 { ::1; };
    directory   "/var/named";
    dump-file   "/var/named/data/cache_dump.db";
    statistics-file "/var/named/data/named_stats.txt";
    memstatistics-file "/var/named/data/named_mem_stats.txt";
-   allow-query     { localhost; };
+   // forwarders  { 192.168.1.54; 192.168.1.55; };
+   allow-query { any; };

-   /* 
-    - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
-    - If you are building a RECURSIVE (caching) DNS server, you need to enable 
-      recursion. 
-    - If your recursive DNS server has a public IP address, you MUST enable access 
-      control to limit queries to your legitimate users. Failing to do so will
-      cause your server to become part of large scale DNS amplification 
-      attacks. Implementing BCP38 within your network would greatly
-      reduce such attack surface 
-   */
-   recursion yes;
-
-   dnssec-enable yes;
-   dnssec-validation yes;
-   dnssec-lookaside auto;
+   /* Allow recursion from Samba server itself and its Windows management system */
+   allow-recursion {
+           192.168.0.17;
+           192.168.1.11;
+   };
+
+   dnssec-enable no;
+   dnssec-validation no;
+   // dnssec-lookaside auto;

    /* Path to ISC DLV key */
    bindkeys-file "/etc/named.iscdlv.key";
@@ -38,7 +33,8 @@
    managed-keys-directory "/var/named/dynamic";

    pid-file "/run/named/named.pid";
-   session-keyfile "/run/named/session.key";
+
+   tkey-gssapi-keytab "/var/lib/samba/private/dns.keytab";
 };

 logging {
@@ -56,3 +52,6 @@
 include "/etc/named.rfc1912.zones";
 include "/etc/named.root.key";

+dlz "example.com" {
+   database "dlopen /usr/lib64/samba/bind9/dlz_bind9_9.so";
+};

The DNS server can also to be authoritative for additional stub zones hosted in the same BIND instance in flat files. For example:

// Additional zones required for EXAMPLE
zone "swisslos.ch" IN {
    type master;
    file "/var/named/swisslos.ch.zone";
};

Change permissions to reach the folders containing the dynamic zones which should be accessible by BIND:

chgrp named /var/lib/samba/private /etc/krb5.conf
chmod g+rx /var/lib/samba/private

If you disabled IPv6 for the system, disable IPv6 as well for BIND, this prevents flooding the logs with unwanted messages. Add the following line to /etc/sysconfig/named:

OPTIONS="-4"

Starting services

Make the Samba system use its Bind recursive DNS server as primary DNS. This is required for proper Samba 4 operation of the Domain Controller. Any external request made by the server will be forwarded through the POP DNS servers.

Edit /etc/sysconfig/network-scripts/ifcfg- and change the DNS1 line to read as follows:

DNS1=192.168.0.17

Then delete all other DNS* lines from the file. Afterwards restart the network:

systemctl restart NetworkManager

Finally start Bind, NTP server and Samba:

systemctl start named
systemctl start samba
systemctl start ntpd

Troubleshooting

For debugging, launch Bind, the NTP server and Samba with the following options to start them in the foreground:

named -u named -f -g -d 2
ntpd -u ntp:ntp -g -I 192.168.23.08 -D 3
samba -i -M single -d 3

MS-SNTP troubleshooting

To troubleshoot NTP settings, perform the following command on the Windows clients to check the Windows Time Service settings and status:

w32tm /query /status /verbose

You should obtain an output like the following:

Leap Indicator: 0(no warning)
Stratum: 4 (secondary reference - syncd by (S)NTP)
Precision: -6 (15.625ms per tick)
Root Delay: 0.0458527s
Root Dispersion: 7.9058500s
ReferenceId: 0xC0A81708 (source IP:  192.168.0.17)
Last Successful Sync Time: 8/19/2013 2:33:08 PM
Source: samba.example.com
Poll Interval: 10 (1024s)

Phase Offset: -0.0377036s
ClockRate: 0.0156007s
State Machine: 1 (Hold)
Time Source Flags: 2 (Authenticated )
Server Role: 0 (None)
Last Sync Error: 0 (The command completed successfully.)
Time since Last Good Sync Time: 34.8648825s

The output identifies the last succesful sync time; the fact that the client / server communication is using MS-SNTP to communicate (Time Source Flags: 2 (Authenticated )), and that the last command was executed successfully.

In case it doesn’t work; to manually set Windows Time Service configuration to read NTP settings from the domain, perform the following commands to reset the configuration and to sync again the client to the server:

w32tm /config /update /syncfromflags:DOMHIER
w32tm /resync

Then check again the status with the previous command.

If the time server specified in the Windows client is a normal NTP server, then the Windows client will not ask for MS-SNTP signed responses. The command to synchronize the clock will be as follows:

w32tm /config /update /syncfromflags:MANUAL
w32tm /resync

This is the output of the query:

Leap Indicator: 0(no warning)
Stratum: 5 (secondary reference - syncd by (S)NTP)
Precision: -6 (15.625ms per tick)
Root Delay: 0.0853119s
Root Dispersion: 7.8537712s
ReferenceId: 0xC0A80101 (source IP:  192.168.1.1)
Last Successful Sync Time: 1/28/2014 3:47:02 PM
Source: 192.168.1.1
Poll Interval: 10 (1024s)

Phase Offset: 0.3340008s
ClockRate: 0.0156001s
State Machine: 1 (Hold)
Time Source Flags: 0 (None)
Server Role: 0 (None)
Last Sync Error: 0 (The command completed successfully.)
Time since Last Good Sync Time: 3.3566832s

Please note that the Time Source Flags do not list the sync as Authenticated.

Kerberos authentication

Test the Active Directory Administrator password and check that the Kerberos ticket and password policies are valid:

$ kinit administrator@EXAMPLE.COM
Password for administrator@EXAMPLE.COM: 
Warning: Your password will expire in 41 days on Mon 20 May 2013 02:19:04 PM CEST
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: administrator@EXAMPLE.COM

Valid starting       Expires              Service principal
04/08/2013 15:45:14  04/09/2013 01:45:14  krbtgt/EXAMPLE.COM@EXAMPLE.COM
    renew until 04/09/2013 15:45:10

SMB/CIFS file sharing

You should now see all your local default shares by browsing:

$ smbclient -L localhost -U%

To test that authentication is working, you should try to connect to the netlogon share using the Administrator password you set earlier:

$ smbclient //localhost/netlogon -UAdministrator%'Password01' -c 'ls'

Required DNS records

To see that all the required DNS records are exposed in the DNS, launch the following commands:

$ host -t SRV _ldap._tcp.example.com.
_ldap._tcp.example.com has SRV record 0 100 389 samba.example.com.
$ host -t SRV _kerberos._udp.example.com.
_kerberos._udp.example.com has SRV record 0 100 88 samba.example.com.
$ host -t A samba.example.com.
samba.example.com has address 192.168.0.17

DNS and GSSEC records insertion/deletion

To test DNS dynamic updates perform the following command on the Windows client:

ipconfig /registerdns

This will create a DNS record for the system in the Active Directory DNS zone using a secure Kerberos authenticated update.

If the record does not appear; start debugging on the server for DNS records availability and proper functioning of the DLZ zone. To proceed launch the following command with both Samba and Bind running:

samba_dnsupdate --verbose --all-names
samba_dnsupdate --verbose

This will fetch all the minimum required DNS records for Active Directory from the Samba database and try to re-insert them into the zone using a kerberized (GSSEC) DNS update to the Bind server.

In case you obtain the message dns_tkey_negotiategss: TKEY is unacceptable while trying to run the command; tis means you have some problems with your current Bind Kerberos keytab file. Perform the following command to check that the service principals are contained in the file:

# klist -k -K -t /var/lib/samba/private/dns.keytab
Keytab name: FILE:/var/lib/samba/private/dns.keytab
KVNO Timestamp           Principal
---- ------------------- ------------------------------------------------------

If you obtain an empty list like the one above, extract the DNS service principal into the file with the following command:

samba-tool domain exportkeytab --principal=DNS/samba.example.com \
    /var/lib/samba/private/dns.keytab

After generation, make sure to check again its contents. If the file is totally corrupt, regenerate it and apply permissions again. You should have some contents like the following:

# klist -k -K -t /var/lib/samba/private/dns.keytab

Keytab name: FILE:/var/lib/samba/private/dns.keytab
KVNO Timestamp           Principal
---- ------------------- ------------------------------------------------------
   1 15/04/2013 14:08:56 DNS/samba.example.com@EXAMPLE.COM (0xd95bd6c789b30d0d)
   1 15/04/2013 14:08:56 DNS/samba.example.com@EXAMPLE.COM (0xd95bd6c789b30d0d)
   1 15/04/2013 14:08:56 DNS/samba.example.com@EXAMPLE.COM (0x9208e7dd4029fe8bdaa18dee16ffb8fc)
   1 15/04/2013 14:08:56 DNS/samba.example.com@EXAMPLE.COM (0x79c8d7df152f3a7d5c42a3fe64248caa4faf854579b66453bea9af7c155286f9)
   1 15/04/2013 14:08:56 DNS/samba.example.com@EXAMPLE.COM (0x5ab2a4df523518d47d3b8f6be79faa2f)

Windows client networking adjustments

Disable NetBios over TCP/IP

To make the necessary tests; make sure that the Windows system has NetBIOS over TCP/IP disabled in the Advanced TCP/IP settings configuration pane.

Disable-netbios

When requesting a resource, Windows 2000 and later systems start two connections simultaneously to a server. One is on port 445 and one on port 139. If the client gets a response from port 445 it will reset (RST) the connection on port 139. If it only gets a response from port 139, that one is used. If you disable NBT (NetBIOS over TCP/IP) on your client; only port 445 is being tried. Pre-Windows 2000 clients (such as windows NT) only use port 139.

Disable Teredo IPv6 Tunneling

To disable IPv6 and Teredo IPv6 Tunnelling execute the following command as an Administrator in the Windows command prompt:

netsh interface teredo set state disabled
netsh int ipv6 isatap set state disabled
netsh int ipv6 6to4 set state disabled

Disable NCSI testing

To disable Network Connectivity Status Indicator checking on Microsoft servers for internet connectivity, start the Group Policy Editor (gpedit.msc); navigate to the correct tree and set “Turn off Windows Network Connectivity Status Indicator active tests” to Enable.

Disable-ncsi

Windows firewall integration

For Windows 7, the following ports need to be enabled in the firewall; all the other rules should be disabled. This is a subset of the ones listed in Microsoft’s Active Directory required ports:

Communications from the Windows client towards the domain controller:

  • TCP: 135, 445, 3268, 1024-5000
  • TCP/UDP: 53, 123, 88, 389, 464

Communications from the domain controller towards the Windows clients:

  • TCP: 135, 445, 1024-1048

TLS support for LDAP (local domain on 389 and Global Catalogue on 3268) is disabled because connections are made with SASL, using GSS-API and thus employing Kerberos and session-level encryption. For details on message integrity (signing) and message confidentiality (sealing) please see this nice article from the University of Washington that explains authentication in a simple way.

RPC ports can be as low as one, but in this case you lose a lot of the functionality. For example, running a scheduled task on Windows will open an additional RPC port (yes, that’s true), and if the system does not have any one that can be used, the process fails miserably. From my test in our office, 24 ports should be enough for domain management plus normal day to day desktop use.

To make the RPC server listen on port range 1024-1048; the following registry file needs to be applied and the system rebooted:

Windows Registry Editor Version 5.00
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Rpc\Internet]
"Ports"=hex(7):31,00,30,00,32,00,34,00,2d,00,31,00,30,00,34,00,38,00,00,00,00,\
  00
"PortsInternetAvailable"="Y"
"UseInternetPorts"="Y"

Please note, the following Windows commands will still return the full list of RPC ports for Windows services:

netsh int ipv4 show dynamicport udp
netsh int ipv4 show dynamicport tcp

These are the commands required to add the Windows Firewall rules from the command line; they assume you want to enable the full 192.168.0.0/24 network where the Domain Controller will reside:

netsh advfirewall firewall add rule name="Samba-TCP-In" protocol=TCP localport="135,445,1024-1048" action=allow dir=IN remoteip=192.168.0.0/24
netsh advfirewall firewall add rule name="Samba-TCP-Out" protocol=TCP localport="53,88,123,135,389,445,464,1024-5000,3268" action=allow dir=OUT remoteip=192.168.0.0/24
netsh advfirewall firewall add rule name="Samba-UDP-Out" protocol=UDP localport="53,88,123,389,464" action=allow dir=OUT remoteip=192.168.0.0/24

To debug connections, use the PortQueryUI command that you can download from the Microsoft website:

  • http://www.microsoft.com/en-us/download/details.aspx?id=24009

In case you’re guessing what are those weird record types (like RT) you see queried in Samba’s DNS by Windows Clients, please look at the following links:

  • http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
  • http://technet.microsoft.com/en-us/library/cc758321%28v=ws.10%29.aspx

Experimental CUDA packages

nv-cuda-2014header-updated

I’ve created experimental CUDA packages that try to follow Fedora packaging guidelines as close as possible. Those have been updated to the Nvidia Fedora 20 repository, and are installable through normal yum commands.

To install them, you need to use my repository that contains the latest drivers.

32 bit support

Nvidia is slowly fading out 32 bit support from CUDA, and you can see it reflected in the various packages. The Unified Video Memory kernel module (nvidia-uvm.ko has been removed in version 346.16, CUDA graphical programs are 64 bit only, many libraries and compilers are available in 64 bit only, etc.

Package testing

I’ve uploaded packages only to the Fedora 20 repository, as they are very big and this is what I’m using at the moment as my main desktop. To help test these, I’ve also added a package for ccminer, a CUDA cryptocurrency miner that links to the packages and requires them to be built. By installing it, all required CUDA runtime libraries should be installed as well.

If all goes well, my plan is to enable CUDA packages for all supported Fedora/CentOS/RHEL distributions and add also package software that in the current form do not use the Nvidia libraries.

As an example, the Blender package in Fedora does not (obviously) link to the CUDA libraries, so no CUDA rendering. On the contrary, the binary that you can download from the Blender website is linked statically to the CUDA libraries at compile time.

After some feedback I will enable them for all the other distributions. So if you need them, please test them.

Packages available

A brief recap on the packages, here we have the full list of drivers and CUDA packages that are available inside the repository folder:

$ ls -1 *nvidia* *cuda*
akmod-nvidia-343.22-2.fc20.x86_64.rpm
cuda-6.5.19-2.fc20.x86_64.rpm
cuda-cli-tools-6.5.19-2.fc20.x86_64.rpm
cuda-devel-6.5.19-2.fc20.i686.rpm
cuda-devel-6.5.19-2.fc20.x86_64.rpm
cuda-docs-6.5.19-2.fc20.noarch.rpm
cuda-extra-libs-6.5.19-2.fc20.i686.rpm
cuda-extra-libs-6.5.19-2.fc20.x86_64.rpm
cuda-libs-6.5.19-2.fc20.i686.rpm
cuda-libs-6.5.19-2.fc20.x86_64.rpm
cuda-nsight-6.5.19-2.fc20.x86_64.rpm
cuda-nvvp-6.5.19-2.fc20.x86_64.rpm
dkms-nvidia-343.22-2.fc20.x86_64.rpm
kmod-nvidia-343.22-2.fc20.x86_64.rpm
nvidia-driver-343.22-1.fc20.x86_64.rpm
nvidia-driver-cuda-343.22-1.fc20.x86_64.rpm
nvidia-driver-cuda-libs-343.22-1.fc20.i686.rpm
nvidia-driver-cuda-libs-343.22-1.fc20.x86_64.rpm
nvidia-driver-devel-343.22-1.fc20.i686.rpm
nvidia-driver-devel-343.22-1.fc20.x86_64.rpm
nvidia-driver-libs-343.22-1.fc20.i686.rpm
nvidia-driver-libs-343.22-1.fc20.x86_64.rpm
nvidia-driver-NvFBCOpenGL-343.22-1.fc20.i686.rpm
nvidia-driver-NvFBCOpenGL-343.22-1.fc20.x86_64.rpm
nvidia-driver-NVML-343.22-1.fc20.i686.rpm
nvidia-driver-NVML-343.22-1.fc20.x86_64.rpm
nvidia-driver-NVML-devel-340.29-1.fc20.i686.rpm
nvidia-driver-NVML-devel-340.29-1.fc20.x86_64.rpm
nvidia-healthmon-340.29-1.fc20.x86_64.rpm
nvidia-libXNVCtrl-343.22-1.fc20.i686.rpm
nvidia-libXNVCtrl-343.22-1.fc20.x86_64.rpm
nvidia-libXNVCtrl-devel-343.22-1.fc20.i686.rpm
nvidia-libXNVCtrl-devel-343.22-1.fc20.x86_64.rpm
nvidia-modprobe-343.22-1.fc20.x86_64.rpm
nvidia-persistenced-343.22-2.fc20.x86_64.rpm
nvidia-settings-343.22-1.fc20.x86_64.rpm
nvidia-xconfig-343.22-1.fc20.x86_64.rpm

Package bundles

From the above list, packages can be grouped as follows for an x86_64 system. For additional details, please see the repository page.

Kernel modules, in both akmod and dkms variants. Instantiated kernel modules are available as rebuild in both by enabling the appropriate configuration on your system.

akmod-nvidia
dkms-nvidia
kmod-nvidia

These are the basic driver packages, they are what is required along the kernel module packages to have accelerated drivers and full OpenGL support for a normal desktop. That is gaming, office use, etc. But no CUDA support.

nvidia-driver
nvidia-driver-libs.i686
nvidia-driver-libs
nvidia-libXNVCtrl
nvidia-libXNVCtrl.i686
nvidia-settings

Then we have the CUDA libraries and tools that are part of the drivers and not of the full CUDA toolkit, as they are closely tied to the drivers:

nvidia-driver-cuda
nvidia-driver-cuda-libs.i686
nvidia-driver-cuda-libs
nvidia-persistenced

Then there are extra tools and libraries, like Framebuffer Compression OpenGL libraries, GPU Deployment Kit (NVML, also called Nvidia Management Library), command line configuration for very specific X.org setups and a tool that leverages the NVML library to perform health checks on GPU clusters.

Please note that the Nvidia Management Library headers and tools do not follow the same versioning of the main driver set as they are provided by Nvidia in a separate bundle that is compatible across multiple releases of the drivers. For example, at the time of writing this, we have 340.58 (long lived), 343.22 (short lived) and 346.18 (beta) drivers available.

All works with version 340.29 of the NVML libraries.

nvidia-driver-NvFBCOpenGL.i686
nvidia-driver-NvFBCOpenGL
nvidia-driver-NVML.i686
nvidia-driver-NVML
nvidia-healthmon
nvidia-modprobe
nvidia-xconfig

Lastly, we have all the development files (unversioned library symlinks, headers and documentation) for compiling programs that link to the above driver libraries.

nvidia-driver-devel.i686
nvidia-driver-devel
nvidia-driver-NVML-devel.i686
nvidia-driver-NVML-devel

After those, that have been provided here for more than a year, I’ve now added CUDA packages. These can be splitted into multiple components as well; first group contains most runtime components for simply running CUDA enabled programs:

cuda-libs.i686
cuda-libs
cuda-extra-libs.i686
cuda-extra-libs

Then we have development files (headers, stub libraries, documentation, compilers, etc.) for compiling programs that link to the CUDA libraries:

cuda
cuda-cli-tools
cuda-devel.i686
cuda-devel
cuda-docs.noarch

And then finally, we have Java GUI programs (debuggers, etc.):

cuda-nsight
cuda-nvvp

Official Nvidia repositories

All the packages provide/require/obsolete the relevant driver packages in the RPMFusion repository and all the CUDA packages in the Nvidia repository; so you can enable this repository along with the official Nvidia CUDA one and RPMFusion at the same time. Packages will get upgraded accordingly.