August 14, 2019

Getting Started wth Docker Links

In this blog we will create two docker container and link them together. We will first use mysql image and name that 'mysql', then containerize a simple java web application that links to the mysql container.

Lets begin with the mysql container, lets see the documentation, how to start it.

$ docker run -d -p 3306:3306 --name mysql --rm -e MYSQL_ROOT_PASSWORD=redhat123 -e MYSQL_DATABASE=mydb -e MYSQL_USER=mydb_admin -e MYSQL_PASSWORD=redhat123 mysql:5.7.27

Lets also verify the database.

$ mysql -u mydb_admin -h -p mydb
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.27 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [mydb]> select 1;
| 1 |
| 1 |
1 row in set (0.001 sec)

MySQL [mydb]> exit

You can also run docker ps to check that the mysql container is up and running.

Now lets create our simple java web docker image. We begin by creating a new dockerwar/pom.xml, we use the template from, but change Java EE version to 8 and add mysql-connector-java dependency. Finally we strip the version from the build war file, by overriding <finalName>.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="" xmlns:xsi=""

Then we create a simple static web page dockerwar/src/main/webapp/index.html

<!DOCTYPE html>
        <title>Start Page</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <h1>Hello World!</h1>

Now we need to write our Dockerfile. We will use wildfly for this. Lets open documentation and find latest tag - Then we also need to understand a little more how the jboss wildfly docker image works, so lets open up the source code -

FROM jboss/wildfly:17.0.1.Final
COPY target/dockerwar.war $JBOSS_HOME/standalone/deployments

Now lets test our docker image.

$ mvn clean install 

$ docker build -t dockerwar:1.0.0 .

$ docker run -it -p 8080:8080 --name dockerwar --rm dockerwar:1.0.0

$ curl

Now lets implement a super simple JDBC call from the java web app - src/main/webapp/mysql.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="java.sql.*"%>
<!DOCTYPE html>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

                Connection connection = null;
                try {
                    connection = DriverManager.getConnection("jdbc:mysql://mysql:3306/mydb", "mydb_admin", "redhat123");
                    Statement statement = connection.createStatement();
                    ResultSet resultSet = statement.executeQuery("SELECT 1");
                    while ( {
                        out.println(resultSet.getString(1) + ", ");
                } finally {
                    if (connection != null) {
                        try {
                        } catch (Exception IGNORE) {

Then rebuild java web app och docker image.

$ mvn clean install 

$ docker build -t dockerwar:1.0.0 .

But when we start the java web app, we run the docker container in background and add --link mysql.

$ docker run -d -p 8080:8080 --name dockerwar --rm --link mysql dockerwar:1.0.0

$ curl

So how does these linking work? Lets connect to the java web app docker container.

$ docker exec -it dockerwar bash
[jboss@8954c6a27efd ~]$ cat /etc/hosts localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters mysql 625eb5301cf9 8954c6a27efd

We see that docker has added the mysql hostname to the /etc/hosts. We can also verify the IP by

$ docker inspect mysql | grep IP
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
                    "IPAMConfig": null,
                    "IPAddress": "",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,

And the docker container ID, by docker ps

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
8954c6a27efd        dockerwar:1.0.0     "/opt/jboss/wildfly/…"   2 minutes ago       Up 2 minutes>8080/tcp              dockerwar
625eb5301cf9        mysql:5.7.27        "docker-entrypoint.s…"   59 minutes ago      Up 59 minutes>3306/tcp, 33060/tcp   mysql

August 12, 2019

Getting Started with Creating Docker Images

To build a docker image you create a text file named Dockerfile. Example

FROM debian:jessie
RUN apt-get update && apt-get install -y git

Now lets build a docker image, with a tag (-t) mydebian and set version to 1.0.

$ docker build -t mydebian:1.0 .
Sending build context to Docker daemon  49.14MB
Step 1/2 : FROM debian:jessie
jessie: Pulling from library/debian
e7a7e6031030: Pull complete 
Digest: sha256:a8ae3c5129fb2e10a62b5c059a24308831508c44018c24ccda2e4fc6fd7cdda7
Status: Downloaded newer image for debian:jessie
 ---> 652b7a59e393
Step 2/2 : RUN apt-get update && apt-get install -y git
 ---> Running in 407556d4679a
Get:1 jessie/updates InRelease [44.9 kB]
Ign jessie InRelease
Running hooks in /etc/ca-certificates/update.d....done.
Removing intermediate container 407556d4679a
 ---> 74f740ed80d4
Successfully built 74f740ed80d4
Successfully tagged mydebian:1.0

Verify the new local docker image exists.

$ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED              SIZE
mydebian                    1.0                 74f740ed80d4        About a minute ago   224MB

Lets test it and verify that git is installed.

$ docker run -it --rm --name mydebian mydebian:1.0
root@4ebe6d58927a:/# git --help
usage: git [--version] [--help] [-C ] [-c name=value]

Now lets look at a more complex Dockerfile. We are going to docker containerized a simple python web -

# vi app/

from flask import Flask
app = Flask(__name__)

def hello():
    return "Hello World!"

if __name__ == "__main__":'')

We copied the getting started example, but modified so it binds to all network interfaces - default is only Now lets create our dockerfile.

$ vi Dockerfile

FROM python:3.5
RUN pip install Flask
RUN useradd --create-home --shell /bin/bash appuser
USER appuser
COPY app /app
CMD ["python", ""]
FROM, from which base image
RUN, run a bash command
USER, swich container user
WORKDIR, switch default working directory for container user
COPY, copy a file into container image
CMD, start the container with following command

Now lets build our docker image, named myflask with version 1.0.

$ docker build -t myflask:1.0 .
Sending build context to Docker daemon  3.584kB
Step 1/7 : FROM python:3.5
3.5: Pulling from library/python
5ae19949497e: Pull complete 
ed3d96a2798e: Pull complete 
f12136850781: Pull complete 
1a9ad5d5550b: Pull complete 
6f18049a0455: Pull complete 
8daf83b35d32: Pull complete 
9e89e2e794a3: Pull complete 
da6fafdc8b3e: Pull complete 
a6fb723ae44c: Pull complete 
Digest: sha256:4598d4365bb7a8628ba840f87406323e699c4da01ae6f926ff33787c63230779
Status: Downloaded newer image for python:3.5
 ---> 4ae385ba9dd2
Step 2/7 : RUN pip install Flask
 ---> Running in f8e6adfe71ac
Collecting Flask
  Downloading (94kB)
Collecting Jinja2>=2.10.1 (from Flask)
  Downloading (124kB)
Collecting Werkzeug>=0.15 (from Flask)
  Downloading (328kB)
Collecting itsdangerous>=0.24 (from Flask)
Collecting click>=5.1 (from Flask)
  Downloading (81kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.10.1->Flask)
Installing collected packages: MarkupSafe, Jinja2, Werkzeug, itsdangerous, click, Flask
Successfully installed Flask-1.1.1 Jinja2-2.10.1 MarkupSafe-1.1.1 Werkzeug-0.15.5 click-7.0 itsdangerous-1.1.0
WARNING: You are using pip version 19.2.1, however version 19.2.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Removing intermediate container f8e6adfe71ac
 ---> a44415ad05ad
Step 3/7 : RUN useradd --create-home --shell /bin/bash appuser
 ---> Running in 3cf59ce0bbfc
Removing intermediate container 3cf59ce0bbfc
 ---> d7751c403945
Step 4/7 : USER appuser
 ---> Running in 5cd1ce07c45b
Removing intermediate container 5cd1ce07c45b
 ---> 97d574a5c01e
Step 5/7 : WORKDIR /app
 ---> Running in 268051f212e0
Removing intermediate container 268051f212e0
 ---> 0289a837efa2
Step 6/7 : COPY app /app
 ---> 0d17013d0e9d
Step 7/7 : CMD ["python", ""]
 ---> Running in 5d3194da4321
Removing intermediate container 5d3194da4321
 ---> e7cbc78bff46
Successfully built e7cbc78bff46
Successfully tagged myflask:1.0

Lets test it

$ docker run -d -p 5000:5000 --name myflask --rm myflask:1.0

$ curl
Hello World!

Getting Started with Docker

First install Docker CE, see

To run docker containers, you can either run them in the foreground or the background.


$ docker run -i -t busybox:1.31.0
Unable to find image 'busybox:1.31.0' locally
1.31.0: Pulling from library/busybox
ee153a04d683: Pull complete 
Digest: sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70
Status: Downloaded newer image for busybox:1.31.0
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
-i, run interactively
-t, connect with terminal, i.e. with same terminal as open.

To exit simply, type exit, as exiting from a normal terminal window.


$ docker run -d -p 8080:80 nginx:1.17.2
Unable to find image 'nginx:1.17.2' locally
1.17.2: Pulling from library/nginx
f5d23c7fed46: Pull complete 
918b255d86e5: Pull complete 
8c0120a6f561: Pull complete 
Digest: sha256:eb3320e2f9ca409b7c0aa71aea3cf7ce7d018f03a372564dbdb023646958770b
Status: Downloaded newer image for nginx:1.17.2
-d, run container as daemon
-p, port mapping, part local port 8080 to container port 80

Now lets test with curl

$ curl
<!DOCTYPE html>
<title>Welcome to nginx!</title>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href=""></a>.<br/>
Commercial support is available at
<a href=""></a>.</p>

<p><em>Thank you for using nginx.</em></p>

To see current running containers, use docker ps

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
aa32c45c0cf9        nginx:1.17.2        "nginx -g 'daemon of…"   3 minutes ago       Up 3 minutes>80/tcp   thirsty_proskuriakova

To stop a docker container use docker stop aa32c45c0cf9 or docker kill aa32c45c0cf9, to stop it not gracefully.

All docker containers get automatically an ID, to give it a more friendly name use --name mynginx, but since containers ID needs to be unique, you cannot stop the container and rerun again with same name. To avoid that you can remove the container "history" with --rm

$ docker run -d -p 8080:80 --name mynginx --rm nginx:1.17.2

Now if you stop nginx and lets all process, you will not see nginx.

$ docker stop mynginx

$ docker ps -a

When you need to debug, these commands are useful:

$ docker logs <CONTAINERID|NAME>

$ docker inspect <CONTAINERID|NAME>

And to connect to docker container

$ docker exec -it <CONTAINERID|NAME> bash

More complex containers take input parameters - environment variable. Lets open up dockerhub and the official mysql repository - When you scroll down that page you see several environment variables. Lets test them. NOTE that MYSQL_ROOT_PASSWORD is mandatory.

$ docker run -d -p 3306:3306 --name mysql --rm -e MYSQL_ROOT_PASSWORD=redhat123 -e MYSQL_DATABASE=mydb -e MYSQL_USER=mydb_admin -e MYSQL_PASSWORD=redhat123 mysql:8.0.17

Now lets test to connect from the docker host.

$ mysql -u mydb_admin -h -p mydb
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.17 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [mydb]> 

August 11, 2019

Install Docker Community Edition (CE) on Fedora 30

Uninstall old versions.

# dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine

Install the dnf-plugins-core package which provides the commands to manage your DNF repositories from the command line.

# dnf install -y dnf-plugins-core

Install Docker Community Edition (CE) stable repository.

# dnf config-manager --add-repo

Install Docker Community Edition (CE).

# dnf install -y docker-ce docker-ce-cli

Start Docker.

# systemctl start docker; systemctl enable docker

Test it

# docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:

Running docker as non privilege user

docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.26/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

To run docker as non privileges user, you need to add that user to the docker group and then login out and login in again.

sudo usermod -a -G docker $USER

August 10, 2019

Stream Movies on Fedora 30 from Netflix

To enable the Free repository, use:

sudo dnf install$(rpm -E %fedora).noarch.rpm

Optionally, enable the Nonfree repository:

sudo dnf install$(rpm -E %fedora).noarch.rpm

sudo dnf install ffmpeg

August 9, 2019

Installing Dogtag on Fedora 30 with SoftHSM

Official Documentation



Check OS version.

# cat /etc/redhat-release 
Fedora release 30 (Thirty)

This is a lab setup, so we disable local firewall. This should never be done in production, but here we we want to focus on Dogtag and SoftHSM.

# systemctl stop firewalld; systemctl disable firewalld

The same goes for DNS, hardcode it.

# hostnamectl set-hostname dogtag-10.7.0-hsm.magnuskkarlsson.local

# ip addr show
    inet brd scope global dynamic noprefixroute enp1s0

# echo " dogtag-10.7.0-hsm.magnuskkarlsson.local" >> /etc/hosts

And finally patch and reboot to make sure all new patches are installed.

# yum update -y

# reboot

389 Directory Server ( - Installation of just Base DS

# yum install -y 389-ds-base 389-ds-base-legacy-tools

Difference between 389 DS packages 
        Description : The 389 Directory Server, Administration Server, and Console Suite provide
            : the LDAPv3 server, the httpd daemon used to administer the server, and the
            : console GUI application used for server and user/group administration.

        Description : 389 Directory Server is an LDAPv3 compliant server.  The base package includes
                    : the LDAP server and command line utilities for server administration.

The system user the 389 DS is running as.

# grep dirsrv /etc/passwd; grep dirsrv /etc/group
dirsrv:x:389:389:user for 389-ds-base:/usr/share/dirsrv:/sbin/nologin

Configure 389 DS with

# --silent \
    General.FullMachineName='dogtag-10.7.0-hsm.magnuskkarlsson.local' \
    General.SuiteSpotUserID=dirsrv \
    General.SuiteSpotGroup=dirsrv \
    slapd.ServerPort=389 \
    slapd.ServerIdentifier=pki-tomcat \
    slapd.Suffix=dc=magnuskkarlsson,dc=se \
    slapd.RootDN="cn=Directory Manager" \
Your new DS instance 'pki-tomcat' was successfully created.
Exiting . . .
Log file is '/tmp/setup7Mv_YS.log'

Check installation log, that everything is OK.

# cat /tmp/setup7Mv_YS.log
[19/08/07:11:06:49] - [Setup] Info Your new DS instance 'pki-tomcat' was successfully created.
[19/08/07:11:06:49] - [Setup] Success Exiting . . .
Log file is '/tmp/setup7Mv_YS.log'

Test and verify 389 installation, by simple query.

# ldapsearch -x -h dogtag-10.7.0-hsm.magnuskkarlsson.local -p 389 -s base -b "" "objectclass=*" 

# extended LDIF
# LDAPv3
# base <> with scope baseObject
# filter: objectclass=*
# requesting: ALL

objectClass: top
defaultnamingcontext: dc=magnuskkarlsson,dc=se
dataversion: 020190807090649
netscapemdsuffix: cn=ldap://dc=dogtag-hsm,dc=magnuskkarlsson,dc=local:389

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

To start all instances.

# systemctl enable; systemctl start

To start specific instance.

# systemctl status dirsrv@pki-tomcat.service

Install Dogtag (10.7.0-1.fc30)

# yum install -y dogtag-pki

SoftHSM (2.5.0-3.fc30.1)

The Dogtag HSM configuration is not always complete, but here it is

# yum install -y softhsm

Configure a new slot in SoftHSM named "Dogtag" and with PIN "redhat123".

# softhsm2-util --init-token --label "Dogtag" --so-pin redhat123 --pin redhat123 --free

Since we are initializing the SoftHSM as root and Dogtag is running as pkiuser, we need to add file permission. Here we add all permission, since using SoftHSM is only for development and testing HSM, in production you use a real HSM.

# chmod 777 /var/lib/softhsm -Rv


p11-kit is a new feature in Fedora 29 and 30. We need to disable it, otherwise will Dogtag installation script not work.

# rm -f /etc/crypto-policies/local.d/nss-p11-kit.config && update-crypto-policies

# reboot

Bugg 3093 Installation Script Ignore sslserver Token Configuration

Implement above pull 230. Comment 'token = pki.nssdb.normalize_token(token)'

# vi /usr/lib/python3.7/site-packages/pki/server/deployment/
    def normalize_cert_token(self, name):

        # get cert token
        token = self.mdict.get(name)

        # if not specified, get default token name
        if not token:
            token = self.mdict.get('pki_token_name')

        # normalize token name
        # token = pki.nssdb.normalize_token(token)

        # update cert token
        self.mdict[name] = token

Also hardcode sslserver token to internal 'token = pki.nssdb.INTERNAL_TOKEN_NAME'

# vi /usr/lib/python3.7/site-packages/pki/server/deployment/scriptlets/
    def import_perm_sslserver_cert(self, deployer, instance, cert):

        nickname = cert['nickname']
        token = pki.nssdb.normalize_token(cert['token'])

        if not token:
            token = deployer.mdict['pki_token_name']

        # BUG FIX hardcoded value
        token = pki.nssdb.INTERNAL_TOKEN_NAME
            'Importing permanent SSL server cert into %s token: %s',
            token, nickname)

        tmpdir = tempfile.mkdtemp()
        nssdb = instance.open_nssdb(token)

            pem_cert = pki.nssdb.convert_cert(cert['data'], 'base64', 'pem')

            cert_file = os.path.join(tmpdir, 'sslserver.crt')
            with open(cert_file, 'w') as f:



Install Dogtag CA (10.7.0-1.fc30)

# vi /root/dogtag-ca-softhsm.cfg




pki_ds_bind_dn=cn=Directory Manager


# pkispawn -f /root/dogtag-ca-softhsm.cfg -s CA

Log file: /var/log/pki/pki-ca-spawn.20190808224648.log
Loading deployment configuration from /root/dogtag-ca-softhsm.cfg.
WARNING: The 'pki_ssl_server_token' in [CA] has been deprecated. Use 'pki_sslserver_token' instead.
Installing CA into /var/lib/pki/pki-tomcat.
Storing deployment configuration into /etc/sysconfig/pki/tomcat/pki-tomcat/ca/deployment.cfg.
Module "softhsm" added to database.
Notice: Trust flag u is set automatically if the private key is present.
The unit files have no installation config (WantedBy=, RequiredBy=, Also=,
Alias= settings in the [Install] section, and DefaultInstance= for template
units). This means they are not meant to be enabled using systemctl.
Possible reasons for having this kind of units are:
• A unit may be statically enabled by being symlinked from another unit's
  .wants/ or .requires/ directory.
• A unit's purpose may be to act as a helper for some other unit which has
  a requirement dependency on it.
• A unit may be started when needed via activation (socket, path, timer,
  D-Bus, udev, scripted systemctl call, ...).
• In case of template units, the unit is meant to be enabled with some
  instance name specified.

                                INSTALLATION SUMMARY

      Administrator's username:             caadmin
      Administrator's PKCS #12 file:

      Administrator's certificate nickname:
      Administrator's certificate database:

      This CA subsystem of the 'pki-tomcat' instance
      has FIPS mode enabled on this operating system.

      REMINDER:  Don't forget to update the appropriate FIPS
                 algorithms in server.xml in the 'pki-tomcat' instance.

      To check the status of the subsystem:
            systemctl status pki-tomcatd@pki-tomcat.service

      To restart the subsystem:
            systemctl restart pki-tomcatd@pki-tomcat.service

      The URL for the subsystem is:

      PKI instances will be enabled upon system boot



Check Dogtag NSS database and that HSM token is there and sslserver is only stored locally.

# echo redhat123 > password.txt

# certutil -L -d /var/lib/pki/pki-tomcat/alias -h all -f password.txt

Certificate Nickname                                         Trust Attributes

sslserver                                                    u,u,u
ca_audit_signing                                             u,u,Pu
ca_signing                                                   CTu,Cu,Cu
Dogtag:ca_signing                                            CTu,Cu,Cu
Dogtag:ca_audit_signing                                      u,u,Pu
Dogtag:ca_ocsp_signing                                       u,u,u
Dogtag:subsystem                                             u,u,u

Test to connect with Dogtag by creating a User NSS DB ~/.dogtag/nssdb. First initialize it.

# pki -c redhat123 client-init

Add new Dogtag CA as trusted CA. To do that we first need to export it from Dogtag NSS DB.

# certutil -L -d /var/lib/pki/pki-tomcat/alias -n "ca_signing" -a -o ca_signing.crt

Then import it to Local User NSS DB.

# pki -c redhat123 client-cert-import --pkcs12 ~/.dogtag/pki-tomcat/ca_admin_cert.p12 --pkcs12-password-file ~/.dogtag/pki-tomcat/ca/pkcs12_password.conf
Imported certificates from PKCS #12 file

And finally import the new generated admin P12 file.

# pki -c redhat123 client-cert-import --pkcs12 ~/.dogtag/pki-tomcat/ca_admin_cert.p12 --pkcs12-password-file ~/.dogtag/pki-tomcat/ca/pkcs12_password.conf
Imported certificates from PKCS #12 file

Now we are ready to query Dogtag.

# pki -c redhat123 -n caadmin ca-user-show caadmin
User "caadmin"
  User ID: caadmin
  Full name: caadmin
  Type: adminType
  State: 1

August 6, 2019

Things To Do After Installing Fedora 30

Disable Natural Scrolling

Disable the Alert Sound

Disable the alert sound, when e.g. tabbing for auto completion in the terminal window

Update and if Necessary Reboot

# yum -y update

Install KVM

# yum -y install qemu-kvm libvirt virt-install bridge-utils virt-manager
# systemctl start libvirtd
# systemctl enable libvirtd

Install GNOME Tweak Tool

# yum -y install gnome-tweak-tool

New Document or Nautilus templates

Install Chrome Web Browser

# yum -y install chromium

Dell XPS

For Dell XPS might not the right click on touchpad work, see