Skip to content

Instantly share code, notes, and snippets.

@rmi1974
Last active March 29, 2020 15:58
Show Gist options
  • Save rmi1974/027d5979c60f1f9e46807e4e3eddc9f8 to your computer and use it in GitHub Desktop.
Save rmi1974/027d5979c60f1f9e46807e4e3eddc9f8 to your computer and use it in GitHub Desktop.
Multi-User Wine installation #wine #commandlinefu

Multi-User Wine installation

Courtesy of Gregory Bartholomew WineHQ Forum post

Step 1 -- Create the Template WINE Installation

Set the WINEPREFIX environment variable to /var/wine and run wine to create your template wine installation, i.e.

sudo mkdir /var/wine; sudo chown $USER /var/wine; WINEPREFIX=/var/wine wine winecfg

Once you have a working wine installation in /var/wine, move it somewhere (e.g. mv /var/wine /var/wine.template) so that you can set up a new /var/wine directory that will be handled by pam_namespace.

Step 2 -- Configure PAM Namespace

Create a new, empty /var/wine directory to be handled by pam_namespace

mkdir /var/wine

chmod 0000 /var/wine

Add the /var/wine directory to pam_namespace

cat < EOF >> /etc/security/namespace.conf
/var/wine /var/wine/ user root,gdm
EOF

Enable pam_namespace

cat < EOF >> /etc/pam.d/system-auth
session [default=ignore] pam_namespace.so ignore_instance_parent_mode
session [default=ignore] pam_exec.so /etc/security/wine.init
EOF

Step 3 -- Create the script that initializes WINE on user logon.

Following is a script that will mount a copy-on-write disk image to /var/wine. pam_namespace will see to it that each user will see their own disk image. There is a lot of "magic" going on in this script -- pam_namespace, dmsetup snapshot, and sparse files. The end result is a multi-user wine installation with minimal disk usage.

Here are a few web links that explain some of the basics:

Create a script /etc/security/wine.init with following content:

#!/bin/sh -p

user=$PAM_USER

pwd=$(getent passwd $user)
uid=$(echo $pwd | cut -d ':' -f 3)
gid=$(echo $pwd | cut -d ':' -f 4)

winedir="/var/wine"
diskdir="$winedir-snapshots"
srcdisk="$diskdir/template"
usrdisk="$diskdir/$user"
srcsize=$(du --apparent-size --block-size=512 "$srcdisk" 2>/dev/null | cut -f 1)

template=$(/sbin/losetup --associated "$srcdisk" | cut -d ':' -f 1)
instance=$(/sbin/losetup --associated "$usrdisk" | cut -d ':' -f 1)

if [ -e "$srcdisk" ]; then
if ! [ -e "$usrdisk" ]; then
dd if=/dev/zero of="$usrdisk" bs=512 count=0 seek=$srcsize &>/dev/null
new=1
fi

if [ -z "$template" ]; then
template=$(/sbin/losetup --show --find --read-only "$srcdisk")
fi

if [ -z "$instance" ]; then
instance=$(/sbin/losetup --show --find "$usrdisk")
fi

if ! [ -e "/dev/mapper/$user" ]; then
echo 0 $srcsize snapshot $template $instance p 8 | /sbin/dmsetup create $user &>/dev/null
fi

if ! mount | grep "^/dev/mapper/$user\b" &>/dev/null; then
mount /dev/mapper/$user "$winedir" &>/dev/null
fi

# 7420 was the uid of my template user; you will need to change this to
# whatever is in your /var/wine.template/drive_c/users/ directory (it may be the username)
if ! [ -e "$winedir/drive_c/users/$user" ]; then
ln -s -r "$winedir/drive_c/users/7420" "$winedir/drive_c/users/$user" &>/dev/null
fi

# 7420 was the uid of my template user; you will need to change this to
# whatever is in your /var/wine.template/drive_c/users/ directory (it may be the username)
if ! [ -e "$winedir/drive_c/users/$uid" ]; then
ln -s -r "$winedir/drive_c/users/7420" "$winedir/drive_c/users/$uid" &>/dev/null
fi

if [ "$new" == "1" ]; then
chown --recursive --from=root:root $user:$gid $winedir &>/dev/null
fi
fi

exit 0

Make it executable:

chmod +x /etc/security/wine.init

Step 4 -- Create the template disk image and populate it with the contents of /var/wine.template

mkdir /var/wine-snapshots

Create a sparse file to hold the template wine installation (modify the size as needed)

dd if=/dev/zero of=/var/wine-snapshots/template bs=1MiB count=0 seek=1024

Put a file system in the template file

mkfs.ext4 /var/wine-snapshots/template

Copy the template wine installation to the template file (disk image) and tweak it

mount /var/wine-snapshots/template /mnt

cp -a /var/wine.template/* /mnt

NOTE: 7420 was my uid. Yours will likely be different.

cd /mnt/drive_c/users/7420

Remove any symbolic links and replace them with real directories

find /mnt/drive_c/users/7420 -maxdepth 1 -type l -exec rm -f "{}" \; -exec mkdir "{}" \;

Copy any needed files from the original linked directories to the new real directories. e.g.:

cp "$HOME/Desktop/Google SketchUp 8.desktop" /mnt/drive_c/users/7420/Desktop

cp "$HOME/Desktop/Google SketchUp 8.lnk" /mnt/drive_c/users/7420/Desktop

You might wand to grep for references to your installation username in /mnt/*.reg at this point (e.g. grep jsmith /mnt/*.reg). There shouldn't be any. If there are, they may prevent whatever software you are trying to use from working properly. Ideally, all path references should be anchored in /var/wine (or C:\\). There may be references to the user's uid in C:\\users, but that will be taken care of with a symbolic link that is made by the wine.init script.

chown --recursive root:root /mnt/*

umount /mnt

Copy any needed files from the original template user's home directory to the system-wide location. e.g.:

cp -r ~jsmith/.local/share/applications/wine* /usr/share/applications

cat ~jsmith/.local/share/applications/mimeinfo.cache >> /usr/share/applications/mimeinfo.cache

Make sure that any icons that were copied to /usr/share/applications have the WINEPREFIX variable set correctly. They should look something like the following example:

$ cat /usr/share/applications/google-sketchup.desktop
[Desktop Entry]
Name=Google SketchUp 8
Exec=env WINEPREFIX="/var/wine" wine C:\\\\Program\\ Files\\\\Google\\\\Google\\ SketchUp\\ 8\\\\SketchUp.exe
Type=Application
StartupNotify=true
Icon=A986_SketchUpIcon.0

That should do it! You should now have a working multi-user, "centralized", wine installation.

P.S. I found the following commands useful for setting up the default icons for my Fedora 19 users:

cat <<- "EOF" > /usr/share/glib-2.0/schemas/org.gnome.shell.gschema.override
[org.gnome.shell]
favorite-apps=['firefox.desktop', 'google-chrome.desktop', 'eclipse.desktop', 'netbeans-7.1.2.desktop', 'amarok.desktop', 'gimp.desktop', 'vlc.desktop', 'quoth.desktop', 'kino.desktop', 'fedora-gnomebaker.desktop', 'nautilus.desktop', 'gnome-terminal.desktop', 'inkscape.desktop', 'google-sketchup.desktop']
EOF
glib-compile-schemas /usr/share/glib-2.0/schemas

P.P.S. I forgot to mention in the previous post that you may need to increase the number of loop back devices that are available in the /dev file system. One loop back device will be needed per user and the default number of available devices is 8. If you will be having more than 8 users of wine between reboots of your computer, then you will need to increase the number by adding something like "max_loop=256" to your list of kernel parameters and reloading grub to your boot sector. e.g.:

sed -i '/^GRUB_CMDLINE_LINUX/s|"$| max_loop=256"|' /etc/default/grub

grub2-mkconfig -o /boot/grub2/grub.cfg

grub2-install /dev/sda

Links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment