Install ffmpeg on devuan

If you want to use ffmpeg on devuan (I want to convert mp4 files to mp3), you should use utility avconv from package libav-tools.

References

Weblinks

  1. https://superuser.com/questions/286675/how-to-install-ffmpeg-on-debian/865744#865744
Advertisements

Cinnamon adds “Show all workspaces” setting to Alt-tab appSwitcher

The story

I recently made a pull request to Cinnamon to add the “Show all workspaces” setting to the window list of the panel. To complement this feature, I decided to add the feature to the alt-tab utility.

My journey began with trying to find the alt-tab code in the Cinnamon project. It took me quite a while, but eventually I found it in appSwitcher.js. At first I started tinkering with lines 36-39

function matchWorkspace(win) {
    return win.get_workspace() == this && !win.is_skip_taskbar();
}

But this proved to not be the right spot. Later on I realized this was not the correct spot logically, but putting code here would work. It just wouldn’t make sense underneath the title “matchWorkspace.” You shouldn’t even get to the matchWorkspace function if you’re just showing all workspaces anyway.

So then I found this section of code

            // Switch between windows of same application from all workspaces
            let focused = global.display.focus_window ? global.display.focus_window : windows[0];
            windows = windows.filter( matchWmClass, focused.get_wm_class() );
            break;
        default:
            // Switch between windows of current workspace
            this._showAllWorkspaces = global.settings.get_boolean("alttab-switcher-show-all-workspaces");
            if (!this._showAllWorkspaces) {
                windows = windows.filter( matchWorkspace, global.screen.get_active_workspace() );
            }
            break;
    }

And that was what I wanted. The snippet above already includes my adjustment. Line 73 is the logic that reads the gsettings schema. And it took me a while to get this part to work. At first I had the read-schema code up beside the other global.settings.get_boolean at line 112 in the AppSwitcher.prototype._init: function(binding). But it took me a while to figure out the scoping of the variable was not correct for my needs. Reading the gsetting schema in the prototype did not set the variable for the function at line 73, function getWindowsForBinding(binding).

I also had to learn about the gsettings schema. I’ve dabbled with dconf before. But apparently adding a new key is a little more complicated that just

dconf load /org/cinnamon <<EOF
[/]
alttab-switcher-show-all-workspaces true

I learned that for gsettings you have to modify the xml-defined schema. I found it at /usr/share/glib-2.0/schemas/org.cinnamon.gschema.xml. My addition is pretty basic, at lines 541-545.

    <key type="b" name="alttab-switcher-show-all-workspaces">
      <default>false</default>
      <_summary>Show all windows from all workspaces</_summary>
    </key>

I also found file /usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py and added the widget for this setting.

            widget = GSettingsSwitch(_("Show windows from all workspaces"), "org.cinnamon", "alttab-switcher-show-all-workspaces")
            settings.add_row(widget)

So I made my changes and then restarted Cinnamon. Still no go. After a lot of searching, I finally found the important part: I needed to run glib-compile-schemas!

pushd /usr/share/glib-2.0/schemas; glib-compile-schemas .; popd;

Now I finally had success! I submitted pull request #6938 and within a day my changes were approved and merged.

The commit as a patch

diff --git a/data/org.cinnamon.gschema.xml.in b/data/org.cinnamon.gschema.xml.in
index 71e09aca..17fe5dc4 100644
--- a/data/org.cinnamon.gschema.xml.in
+++ b/data/org.cinnamon.gschema.xml.in
@@ -538,6 +538,11 @@
       <_description>Duration of the effect (in milliseconds)</_description>
     </key>
 
+    <key type="b" name="alttab-switcher-show-all-workspaces">
+      <default>false</default>
+      <_summary>Show all windows from all workspaces</_summary>
+    </key>
+
     <key name="bring-windows-to-current-workspace" type="b">
       <default>false</default>
       <summary>Brings windows requiring attention to the current workspace</summary>
diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py
index 4875346e..080026ab 100755
--- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py
+++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_windows.py
@@ -129,6 +129,9 @@ class Module:
             widget = GSettingsSpinButton(_("Delay before displaying the alt-tab switcher"), "org.cinnamon", "alttab-switcher-delay", units=_("milliseconds"), mini=0, maxi=1000, step=50, page=150)
             settings.add_row(widget)
 
+            widget = GSettingsSwitch(_("Show windows from all workspaces"), "org.cinnamon", "alttab-switcher-show-all-workspaces")
+            settings.add_row(widget)
+
 class TitleBarButtonsOrderSelector(SettingsBox):
     def __init__(self):
         self.schema = "org.cinnamon.muffin"
diff --git a/js/ui/appSwitcher/appSwitcher.js b/js/ui/appSwitcher/appSwitcher.js
index f161350c..d36d3bf2 100644
--- a/js/ui/appSwitcher/appSwitcher.js
+++ b/js/ui/appSwitcher/appSwitcher.js
@@ -70,7 +70,10 @@ function getWindowsForBinding(binding) {
             break;
         default:
             // Switch between windows of current workspace
-            windows = windows.filter( matchWorkspace, global.screen.get_active_workspace() );
+            this._showAllWorkspaces = global.settings.get_boolean("alttab-switcher-show-all-workspaces");
+            if (!this._showAllWorkspaces) {
+                windows = windows.filter( matchWorkspace, global.screen.get_active_workspace() );
+            }
             break;
     }
 

References

Weblinks

  1. Need to use glib-compile-schemas https://developer.gnome.org/gio/stable/GSettings.html
  2. https://developer.gnome.org/GSettings/

I am now an open source contributor!

Overview

I use open-source software every day, since November 2015. That was the year of Linux on the Desktop for me. I picked as my desktop environment Cinnamon.

I normally don’t use virtual desktops or “workspaces,” but on one laptop I was for a while. It was actually a KDE Plasma 5 installation, which reinforced my plans to stick to Cinnamon as my heavyweight DE. However, the KDE Plasma virtual workspaces worked fine, and provided all sorts of options for the window list and alt-tab switcher for listing windows across all the workspaces. Cinnamon did not have such an offering, so when I finally replaced KDE with Cinnamon on that workstation, I just reverted to my single-workspace workflow.

I told someone online (probably in the #korora channel at irc.freenode.net) that I was willing to pay money for Cinnamon to provide a window list option for displaying the windows from all workspaces. Well, as of October 2, I guess I owe myself $50.

Check out my merged pull request to Cinnamon! I added the feature, as a boolean setting, to the mainline Cinnamon window list applet. So eventually my option will be included in the Fedora Cinnamon build down the line. For the time being, though, I’m going to continue to use my separate applet that provides my feature.

Adding Reverse Proxy for Plex to Apache vhost

Introduction

It is easy to find apache vhost definitions for reverse proxying plex traffic.
What this post does is show you how to include the parts needed, to provide a reverse proxy to plex, in an existing vhost. Why would you need this? I don’t know. I did, and it was as easy as adding a few bits to represent the web address.

Adding reverse proxy for plex to Apache vhost

So in your vhost, add these lines:

        <Proxy *>
                Order deny,allow
                Allow from all
        </Proxy>
        ProxyRequests Off
        ProxyPass               /web/   http://www.ipa.example.com:32400/web/
        ProxyPassReverse        /web/   http://www.ipa.example.com:32400/web/
        <LocationMatch '^/web\/.*$'>
                RequestHeader set Front-End-Https "On"
                RewriteEngine On
                RewriteCond     %{REQUEST_URI}          !^/web
                RewriteCond     %{HTTP:X-Plex-Device}   ^$
                RewriteCond %{REQUEST_METHOD}   !^(OPTIONS)$
                RewriteRule ^/$ /web/$1 [R,L]
        </LocationMatch>

So the difference in this snippet from a separate vhost definition is that you proxypass only the /web/ location over to your Plex media server.

<VirtualHost 192.168.1.14:180>

	ServerName	example.no-ip.biz:80
	ServerAlias	example.no-ip.biz example www www.ipa.example.com
	ServerAdmin	bgstack15@gmail.com

	DocumentRoot	/var/www

	Options +Indexes
	IndexOptions IgnoreCase FancyIndexing FoldersFirst NameWidth=* DescriptionWidth=*
	IndexIgnore FOOTER.html repodata favicon.ico favicon.png
	ReadmeName FOOTER.html
	DirectoryIndex index.php index.html index.htm
	ServerSignature Off

	SetEnvIf Request_URI "ignoredfile.html" dontlog
	LogFormat "%V %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedvhost
	CustomLog logs/access_log combinedvhost env=!dontlog

	# Useful additions for a mirror server
	AddIcon /icons/rpm.png          .rpm
	AddIcon /icons/deb.png          .deb
	AddIcon /icons/repo.png         .repo
	AddType application/octet-stream .iso

	AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
	BrowserMatch ^Mozilla/4 gzip-only-text/html
	BrowserMatch ^Mozilla/4\.0[678] no-gzip
	BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

	TraceEnable off
	<FilesMatch "\.acl$">
		Deny from All
	</FilesMatch>
	&ltDirectory "/var/www/example">
		AllowOverride None
		Order allow,deny
		Allow from all
		Options Indexes FollowSymLinks
	</Directory>
 
       # Allows "centos.example.no-ip.biz" redirection to "example.no-ip.biz/centos" behavior
# RewriteEngine On
# RewriteCond %{HTTP_HOST} ^([^.]*)\.example\.no-ip\.biz$
# RewriteRule /(.*) http://example.no-ip.biz/%1/$1 [R,L]

	# reference: welcome.conf, reverseproxyforplex.conf
	# reference: http://matt.coneybeare.me/how-to-map-plex-media-server-to-your-home-domain/
	<Proxy *>
		Order deny,allow
		Allow from all
	</Proxy>
	ProxyRequests Off
	ProxyPass		/web/	http://www.ipa.example.com:32400/web/
	ProxyPassReverse	/web/	http://www.ipa.example.com:32400/web/
	<LocationMatch '^/web\/.*$'>
		RequestHeader set Front-End-Https "On"
	        RewriteEngine On
		RewriteCond	%{REQUEST_URI}		!^/web
		RewriteCond	%{HTTP:X-Plex-Device}	^$
		RewriteCond %{REQUEST_METHOD}	!^(OPTIONS)$	
		RewriteRule ^/$ /web/$1 [R,L]
	</LocationMatch>

</VirtualHost>

References

Weblinks

  1. http://matt.coneybeare.me/how-to-map-plex-media-server-to-your-home-domain/

xfconf-query save and load from file

xfconf-query load from file

Introduction

The wonderful xfce desktop environment provides a mechanism to inspect and modify your settings, similar to dconf. This tool is named xfconf-query, and it allows you to list and modify entries one at a time. Unfortunately, it does not provide a way to export to a file and import, the way dconf does (with standard redirection).

Save settings to file
For xfce, you can display the settings by specifying the channel:

xfconf-query -c thunar -lv

#place sample output here

You can save this to a file with output redirection, but you won’t be able to load this very easily from such a file.

To get the settings in a nicer format for saving to a text file, use this oneliner:

xfconf-query -l | sed -r -e '/Channels:/d' | while read line; do xfconf-query -lv -c "${line}" | sed -r -e "s/^/${line} /"; done > my-settings.xfconf

#place sample output here

xfconf-query load settings from file

I wrote a wrapper script that loads the settings from such a file. Please check out the full xfconf.sh script at github.
Its basic use is very simple. Call the script with the settings file as the only parameter:

xfconf.sh mysettings.xfconf

Code walkthrough

#!/bin/sh
# File: /usr/share/bgconf/inc/xfconf.sh
# Author: bgstack15
# Startdate: 2017-09-17 08:10
# Title: Script that Loads Settings into Xfconf
# Purpose: To make a single interface for other bgconf scripts to call for loading an xfconf file
# History:
#    2017-06 Main research was done but put in separate bgconf scripts.
#    2017-09-17 I decided to separate it out to streamline the bgconf scripts themselves.
# Usage:
#    In a script, determine that an xfconf file exists, then call:
#       xfconf.sh mysettings.xfconf
#    To generate a new xfconf file, you can run:
#       xfconf-query -l | sed -r -e '/Channels:/d' | while read line; do xfconf-query -lv -c "${line}" | sed -r -e "s/^/${line} /"; done > outfile
# Reference:
# Improve:
# Document: Below this line

thisDE=xfce
thisDEconf=xfconf-query
infile="${1}"

# get DBUS_SESSION_BUS_ADDRESS of first DE process of this user
# reference:  https://unix.stackexchange.com/questions/29128/how-to-read-environment-variables-of-a-process/29132#29132
tmpfile1="$( mktemp )"
if test -n "${SUDO_USER}"; then _user="${SUDO_USER}"; else _user="${USER}"; fi
cat /proc/$( ps -eu${_user} | grep -E "${thisDE}" | tail -n1 | awk '{print $1}' )/environ 2>/dev/null | tr '\0' '\n' | grep -E "DBUS_SESSION_BUS_ADDRESS|DISPLAY" > "${tmpfile1}"
test -f "${tmpfile1}" && test $( grep -cE "(DBUS_SESSION_BUS_ADDRESS|DISPLAY)=.+" "${tmpfile1}" 2>/dev/null ) -ge 2 || echo "$0 error: Skipping ${thisDE}: Could not find current session." 1>&2
chmod +rx "${tmpfile1}" 2>/dev/null
. "${tmpfile1}"
/bin/rm -f "${tmpfile1}" 1>/dev/null 2>&1

# Assume infile exists as a file
if test -n "$( cat "${infile}" 2>/dev/null )" && test -x "$( which "${thisDEconf}" )" && ps -ef | grep -qE "${thisDE}" && test -n "${DBUS_SESSION_BUS_ADDRESS}";
then

   # get user of that directory
   thisowner="$( stat -c '%U' "${infile}" )"
   thisowneruid="$( stat -c '%u' "${infile}" )"

   # xfce custom configuration
   grep -viE '^\s*((#|;).*)?$' "${infile}" | while read channel attrib value;
   do

      # display output
      #printf "channel=%s\tattrib=%s\tvalue\%s\n" "${channel}" "${attrib}" "${value}"

      # provide data type. This needs to be researched before making a new .xfconf file.
      _thistype=string
      case "${attrib}" in
         *last-separator-position) _thistype=integer ;;
         *last-show-hidden|*misc-single-click) _thistype=bool ;;
      esac

      # make change
      sudo su - "${thisowner}" -c "DISPLAY=${DISPLAY} DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS} ${thisDEconf} --create -t ${_thistype} -c ${channel} -p ${attrib} -s ${value}"

   done

fi
/bin/rm -f "${tmpfile1}" 2>/dev/null

The line numbers here are different from the script on github, and probably will get outdated as I make improvements to this utility. So I will use line numbers for the version seen above. Also, this script was originally written as a small portion of a larger project to deploy my settings to a whole system. That’s why you’ll see the “sudo – su” and logic to determine file ownership, because it is being called by a command running with sudo.

Lines 23-31 find the running desktop environment for the user (or the user who called sudo) and grab the values for DBUS_SESSION_BUS_ADDRESS and DISPLAY that point to that running desktop environment. I don’t know a more official way, so I assembled this kludge over the course of this project. I’m rather fond of this logic despite the kludgeyness. You will observe on line 30 that this script actually dot sources a temp file with those variables. I actually first used this technique for loading conf files in an attempt to be more unix-like and use environment variables first, and then load in a conf file.

Line 34 calculates the requested file has contents, and the desktop environment really exists and is running, and one of the variables from the previous section is defined.
Lines 42-58 perform the actual import of settings from the file. The interesting regular expression is my official non-blank non-comment regex. For quick hand-typed oneliners, I normally just use ‘^$|^#’ but here I went with the fancier version that handles whitespace.
So the block reads three entries per line, the channel, item, and item value. Then it runs xfconf-query and plugs in the variable.
Lines 48-53 perform a manual type declaration based on hard-coded names. I don’t know how to query that from xfconf-query, so I had to use the graphical xfce settings tool to collect the exact names. You will definitely need to read through your xfconf files to make sure you include all the right options here. I suppose one could find a list of all the datatypes maybe from xfce’s documentation and parse it. I guess I’ll add that to the “Improve:” header.

Samba and ntlm for Windows clients

tl;dr

Use one or the other:

1. Insecure but fast, in /etc/samba/smb.conf:

[global]
ntlm auth = yes

2. Best, on client Windows machine:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
"LmCompatibilityLevel"=dword:00000001

Samba and ntlm

With the published “ETERNALBLUE” vulnerability (CVE-2017-0146) a few months ago, the effects finally trickled down to the default settings for samba in CentOS 7.

After updating to samba 4.6.2, I was unable to access my samba share from a Windows client (using my freeipa credentials).

Here’s what I found in /var/log/samba/log.lsasd after setting [global] log level = 3:

  check_ntlm_password:  Authentication for user [bgstack15] -> [bgstack15] FAILED with error NT_STATUS_WRONG_PASSWORD
[2017/10/01 16:45:54.106771,  2, pid=5289] ../auth/gensec/spnego.c:768(gensec_spnego_server_negTokenTarg)
  SPNEGO login failed: NT_STATUS_WRONG_PASSWORD
[2017/10/01 16:45:54.106860,  3, pid=5289] ../source3/smbd/smb2_server.c:3097(smbd_smb2_request_error_ex)
  smbd_smb2_request_error_ex: smbd_smb2_request_error_ex: idx[1] status[NT_STATUS_LOGON_FAILURE] || at ../source3/smbd/smb2_sesssetup.c:134
[2017/10/01 16:45:54.107513,  3, pid=5289] ../source3/smbd/server_exit.c:246(exit_server_common)
  Server exit (NT_STATUS_CONNECTION_RESET)
[2017/10/01 16:45:54.113588,  3, pid=5249] ../source3/lib/util_procid.c:54(pid_to_procid)
  pid_to_procid: messaging_dgm_get_unique failed: No such file or directory

After lots and lots of research, I finally found the answer at the FreeBSD forum! Gotta love the FreeBSD folks; they keep us all sane and grounded in free and open computing.
Just add ntlm auth = yes to your [global] section of smb.conf!

However, I looked it up and that enables samba to accept ntlmv1, which was the vulnerable protocol based on that CVE I mentioned earlier in this article.

I wanted to find out how to stick to ntlmv2 authentication, if possible, and I did discover it! You can just configure your Windows clients to use the more secure settings either using the registry or the graphical secpol.msc tool.
For the Local Security Policy (secpol.msc) tool, navigate to Security Settings->Local Policies->Security Options->”Network security: LAN Manager authentication level.” Set it to “Send LM & NTLM – use NTLMv2 session security if negotiated.”

secpol.msc utility showing directory tree navigated to Network security: LAN Manager authentication level setting
Local Security Policy window with setting

To automate this setting, you can make a registry file such as ntlmv2.reg with the following contents:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
"LmCompatibilityLevel"=dword:00000001

I recognize this location from when I’ve adjusted it in the past, at a place that would not have been affected by this vulnerability or its remediation because they were forcing NTLMv2 years ago on the workstations.

Reference

Weblinks

      1. Samba quick answer https://forums.freebsd.org/threads/62169/
      2. Client secpol.msc answer https://support.symantec.com/en_US/article.TECH132917.html
      3. Client registry answer https://kb.iu.edu/d/atcb

Create, attach, detach disk to vm in kvm on command line

In kvm, let’s say you want to create a new disk and attach it to a virtual machine. You could use Virtual Machine Manager. But for the command line, here is a quick way how to do it.

Create a disk

Create a qcow2 disk that is fully allocated. When I tried with disks that were not fully allocated, the vm would only see the 200K or so and would not let me write a partition table large enough to do anything.

time qemu-img create -f qcow2 /var/lib/libvirt/images/vmname-vdb.qcow2 22000M -o preallocation=full

Attach a disk

You can omit the flags as needed, if you don’t want to update the virtual machine’s definition, or –config. And some of these are probably redundant, but they did not throw errors for me and I wanted the change to be immediate and persistent upon vm reboot, so I leave them all in.

virsh attach-disk --domain vmname /var/lib/libvirt/images/vmname-vdb.qcow2 --target vdb --persistent --config --live

Detach a disk

Same thing as the attaching, only you don’t include the –target flag.

virsh detach-disk --domain vmname /var/lib/libvirt/images/vmname-vdb.qcow2 --persistent --config --live

References

Weblinks

Man pages

  1. qemu-img

Remove scsi disk from operating system

To tell an OS you are ready to remove a scsi disk, you can run this command:

echo 1 > /sys/block/sdX/device/delete

Where sdX is the device you are ready to detach.

For virtual machines I don’t usually bother doing that, but that is how to safely tell GNU/Linux you are going to remove the device.

References

Weblinks

  1. Original question https://unix.stackexchange.com/questions/31029/echo-1-sys-block-sdx-device-delete-on-all-disks-except-predetermined-list