Add policykit rules for virt-manager

If a user wants to use virt-man to control virtual machines on localhost, he will be prompted to authenticate to policykit.

If you have a policykit rule established (as the libvirt package already provides) for the right group, it’s seamless. Just make sure the user is in group “libvirt” (from /usr/share/polkit-1/rules.d/50-libvirt.rules)
Or, to make a different group the (additional) accepted value:

touch "${tf}" ; chmod 0644 "${tf}"
cat <<EOF >"${tf}"
polkit.addRule(function(action, subject) {
  if ( == "org.libvirt.unix.manage" && subject.local && && subject.isInGroup("wheel")) {
      return polkit.Result.YES;


Web links

    1. How do I prevent virt-manager from asking for the root password? – Super User

LAPS for Linux

A famous non-free operating system vendor provides a Local Administrator Password Solution for its flagship OS.
Here is my attempt at a GNU/Linux client for the same thing. This tool can help store unique local admin passwords in ldap. Some Unix environments still suffer from using the same single root password for everything. Here is the fix for that.
Please note that the domain-side configuration actions are still required. This is only the client-side utility.

laps for linux

Updated 2018-12-07: Now you can just download the rpm from my copr.

This is written in shell, and designed and tested on CentOS 7. An rpm spec is provided if you want to bundle it in that format. Contributions are welcome, of any sort.

There are two main ways to use my laps4linux.

laps is the Local Administrator Password Solution for GNU/Linux.
usage: [-duV] [-c conffile] [-t|-a] [-f] [-r [-u ] [-h ]]
version 2018-10-22a
 -d debug   Show debugging info, including parsed variables.
 -- usage   Show this usage block.
 -V version Show script version number.
 -c conf    Read in this config file. Default is /etc/laps/laps.conf
 -f force   Skip the time check and just update the password regardless.
 --noforce  Do not force. Overrides environment variable LAPS_FORCE.
 -t test    Dry run only. Useful with debugging on.
 -a apply   Turn off dry run. Default.
 -r read    Read password; do not set it. Can only be used by a domain admin. Can only be used with -u.
 -u user    Connect with kerberos ticket for this user. Default is "machine" to use host keytab.
 -h   Read this hostname instead of $( hostname -s )
Debug levels:
 0 Silent
 9 displays sensitive info, specifically the generated password
10 function trace
Environment variables:
 See documentation at /usr/share/doc/laps/ for full explanation.

Additional notes

When implementing laps in your environment, you will want to ensure the ldap connectivity is working. I particularly had trouble with the kerberos auth to the domain controllers for ldaps.

To use for the first time for a Linux client, you will want to use the -f flag, because the undefined expirationTime ldap attribute will cause an error during the time comparison.

Maybe something like this could be implemented in FreeIPA. It’s just a simple schema extension, oh, and some ACLs. I don’t know if FreeIPA has ACLs on attributes, but it sounds like a logical thing to have.

Sysprep for Linux

Named after a famous non-free OS sysprep process, my GNU/Linux sysprep process helps my company when I need to clone existing vms. For some reason my apps teams are incapable of installing their applications again, so they just have me clone the system. I blank it out as much as possible, and then provision it like it’s new.

Deploy the script to the original server and add a cronjob.

    scp -p /etc/ansible/books/test/sysprep/files/ ${th}:~/
    ssh ${th}
    sudo su -
    /bin/cp -pf /home/*/ /root/ ; chmod 0755 /root/ ; chown root.root /root/
    touch "${tf}" ; chown root.root "${tf}" ; chmod 0600 "${tf}"
    cat <<-EOFCRON 1>"${tf}"
@reboot         root    test ! "\$( hostname -s )" = "$( hostname -s )" && test -e /root/ && sleep 20 && /bin/sh -x /root/ cron 1> /root/intermediate-clone.log 2>&1
    exit # leave root shell
    exit # leave ssh to original server

Inject the regular server deployment scripts.
Modify the td and tv variables here as needed.

    pushd "${td}"
    tar -zc -C /etc/ansible/roles/localization -f /tmp/localizations.tgz files
    scp -p /tmp/localizations.tgz "${th}":~
    pushd "${td}/files/${tv}"
    scp -p *.sh "${th}":~
    ssh "${th}"
    sudo su -
    /bin/mv -f /home/bgstack15/*.sh /root/ ; chown root.root /root/*.sh ; chmod 0750 /root/*.sh ;
    tar -zx -C /etc -f /home/*/localizations.tgz ;
    test -e /etc/files && ! test -e /etc/templates && /bin/mv -f /etc/files /etc/templates ;
    chown -R root:root /etc/templates 2>/dev/null ;
    exit # leave root shell
    exit # leave ssh to original server

The cronjob to run the s1_init script will be provided by the intermediate template’s execution of the sysprep script.

Upon cloning the vm, the sysprep script will be executed! Here it is:

# File:
# Location: /etc/ansible/books/test/sysprep/files/
# Author: bgstack15
# Startdate: 2018-10-11 11:39
# Title: Script that Syspreps an Intermediate Server
# Purpose: Convert an intermediate clone of an existing machine to make it more suitable for use as a VM template
# History:
# Usage:
#    On the intermediate template, run this shell script and then power off the vm.
# Reference:
# Improve:
# Documentation:

echo " version 2018-10-12b"

# make verbose
set -x

export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

# continue only if hostname indicates this is an intermediate template
hostname -s | grep -qiE 'tmp$' || exit 0

# clean up cronjob so this script is only called that very first boot of the intermediate template
/bin/rm -f /etc/cron.d/00_sysprep.cron

# prepare cronjob for s1_init for a normal clone deployment
# this is mostly for the eth0 renaming again
touch "${tf}" ; chown root.root "${tf}" ; chmod 0600 "${tf}"
cat <<-EOFCRON 1>"${tf}"
@reboot         root    test ! "\$( hostname -s )" = "$( hostname -s )" && test -e /root/ && /bin/sh -x /root/ cron 1> /root/clone.log 2>&1

# fix rootsh
this_rootsh="$( which rootsh 2>/dev/null )"
touch "${tf}" ; chmod 0755 "${tf}" ; chown root.root "${tf}"
cat < "${tf}"
if test "\$USER" = "root" ; then
  /usr/bin/sudo ${this_rootsh:-/usr/local/bin/rootsh} \$@ --no-syslog

# disable domain connectivity
/bin/rm -f /etc/krb5.keytab /etc/krb5.conf*
service sssd stop ; systemctl stop sssd.service ;
chkconfig sssd off ; systemctl disable sssd.service ;

# disable monitoring
for ts in ccmexecd scx-cimd ;
   service "${ts}" stop ; systemctl stop "${ts}.service"
   chkconfig "${ts}" off ; systemctl disable "${ts}.service"
# remove old ssl certificates
rm -f /etc/opt/microsoft/scx/ssl/*

# clean old log and config files
pushd /var/log
rm -f boot.log* btmp* cron* dmesg* dracut* maillog* messages* prepatch/* rootsh/* sa/* samba/* secure* spooler/* sssd/* syslog* vmware-* wtmp*
pushd /root
rm -f core* *.ansible_backup KASetup*log log.*.txt VMwareTools*gz
rm -rf vmware-tools-distrib
pushd /etc
rm -f *.cfsaved fstab.* fstab-* hosts.20*
# clean ansible bupped files
rm -f *.20*@*~
# clean homedirs and bash histories
find /home -maxdepth 1 -mindepth 1 ! -name 'ansible' ! -name 'bgstack15' -exec rm -rf {} \;
for tf in /home/*/.bash_history ;
   cat /dev/null | tee "${tf}"

# fix networking, rhel6 on vmware
# from project clone RHEL6/
nic_count="$( ip -o l | grep -cE 'eth[0-9]' )"
this_nic="$( ip -o l | grep -oE 'eth[0-9]' | sort | tail -n1 )"
test "${nic_count}" -eq 1 && test "${this_nic}" != "${out_nic}" && {
   sed -i -r -e "s/${this_nic}/${out_nic}/g;" "${this_nic_file}" 2>/dev/null
   sed -i -r -e "s/${this_nic}/${out_nic}/g;" "${out_nic_file}" 2>/dev/null
   test -e "${this_nic_file}" && /bin/mv -f "${this_nic_file}" "${out_nic_file}"
/bin/rm -f /etc/udev/rules.d/70-persistent-net.rules
udevadm control --reload-rules && udevadm trigger
# the change will take effect upon next reboot

# fix iptables rule tied to eth0
sed -i -r -e '/dport 1270/s/-i eth[0-9]* //;' /etc/sysconfig/iptables

# generate new ssh host keys
# but this will also happen in the s1_init script
/bin/rm -rf /etc/ssh/*key*
# but do not actually generate them, because this is still just the intermediate template
#/sbin/service sshd stop ; /bin/sleep 5 ; /sbin/service sshd start ;

# clean up old sudoers backups
rm -f /etc/sudoers.20* /etc/* /etc/sudoers.rpm* /etc/sudoers.d/disable_requiretty.*

# when this process is verified, the template should shut itself down
shutdown -h now ; systemctl poweroff ;

Netgear AC600 usb wnic drivers for Linux

The gist of it.

# download build tools on devuan
sudo apt-get install --reinstall linux-headers-$(uname -r) build-essential

! test "${USER}" = "root" && sudo su -
pushd /usr/src
git clone
cd rtl8812*
time make
time make install
modprobe rtl8812au
test "${USER}" = "root" && exit

# list new nics
sudo iwconfig
# configure wicd to use new nic -- use gui



This post is a shameless rip-off of two other pages:


      Hi, your device…
      Bus 001 Device 006: ID 0846:9052 NetGear, Inc.

      led me to.
      and this led to..
      Which shows your device 0846:9052 NetGear
      has the rtl8812au chip
      and finally the chilli555 fix can be found,,
      Please first do..
      sudo apt-get install –reinstall linux-headers-$(uname -r) build-essential
      and then visit


And the source for the drivers:


Web searches

  1. netgear a6100 linux driver

Ansible find first accessible proxy and use it

If you need to find the first available http proxy and use it for a process, you can use a python snippet to discover it and use it.



  - name: learn which proxy to use
    script: {{ http_proxies | join( " " ) }}
    changed_when: false
    register: open_ports

  - set_fact:
      http_proxy: "{{ open_ports.stdout_lines[0] }}"
    - 'open_ports.stdout | length > 0'
    - 'open_ports.stdout | length = 0'

  - name: use http_proxy environment variable
    script: -i {{ inputvar }}
      http_proxy: "http://{{ http_proxy | default(omit) }}"

The sole output is the first hostname and port available.

# Filename:
# Location: /etc/ansible/roles/install_sccm/files/
# Author: bgstack15
# Startdate: 2018-10-02 10:13
# Title: Script that Gets the First Open Port
# Purpose: Return to standard output the first valid host and port to use as a http proxy
# Project: projects derived from ansible role certreq
# History:
# Usage:
#    in ansible
# Reference:
#    string split
# Improve:
# Documentation:

import socket, sys
from contextlib import closing


def check_socket(host, port):
   with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
      if sock.connect_ex((host,port)) == 0:
         print host + ":" + str(port)
         return True
   return False

x = 0
for myarg in sys.argv:

   # show version
   if myarg == "--version" or myarg == "-V":
      print(sys.argv[0]+" "+GFOP_VERSION)

   x = x + 1
   # skip the script $0 name itself
   if x > 1:
      # split on the colon
      host, port = myarg.split(":",2)
      # short-circuit upon first successful one
      if check_socket(host,int(port)):

Quick script to purge URL from squid proxy

If you have the requisite permissions in squid.conf, you can just use a quick script to purge URLs. I use this for flushing local files I am developing and download to clients with http.

touch "${tf}" ; chmod 0755 "${tf}"
echo <<EOF > "${tf}"
for word in ${@} ;
   squidclient -h localhost -r -p 3128 -m PURGE "${word}"

For squid, I am using a few lines to allow purging:

acl PURGE method PURGE
http_access allow PURGE localhost

Then you can call it:


Firefox trust system trusted certificates

last updated 2019-07-11

Mozilla maintains its own certificate store mechanism (nss), and eschews the system trust store.

Somehow, my Fedora systems that are joined to freeipa work correctly with my ipa certs. I suspect Fedora compiles firefox with the directive to read the /etc/ipa/nss directory. On Devuan I have not had success with that location, nor /etc/pki/nss. All of this is still a bit voodoo to me, and it’s sad that Firefox trusts [] the Windows system trusted root cert store but not the GNU/Linux one.

To programmatically add your root ca certs to the existing firefox profiles, use a shell scriptlet lifted from firefox – Programmatically Install Certificate Into Mozilla []:

certificateName="MyCA Name" 
for certDB in $(find  ~/.mozilla* ~/.thunderbird -name "cert8.db")
  certDir=$(dirname ${certDB});
  #log "mozilla certificate" "install '${certificateName}' in ${certDir}"
  certutil -A -n "${certificateName}" -t "TCu,Cuw,Tuw" -i ${certificateFile} -d ${certDir}

For new users, you probably need to do this to /etc/skel/.mozilla/firefox/*.default.


An easier way is possible on debian-based distros with the p11-kit package. After installing that package, you can configure Firefox to include the library in the “Security Devices” in about:preferences -> Privacy and Security tab.

Select the “Load” button to add a new entry, and name it something and specify the full path to the library. On Devuan ceres, my file was /usr/lib/x86_64-linux-gnu/pkcs11/

It would not hurt to restart Firefox, but I think the change was immediate for me.


Internet searches

firefox p11-trust


  1. Original
  2. Kernel of idea for p11-kit
  3. Simple instructions