Compare commits

..

13 commits

Author SHA1 Message Date
Troy Dawson
8fa8ffc5e5 Fix ghost file permissions
Signed-off-by: Troy Dawson <tdawson@redhat.com>
2025-10-21 11:58:00 -07:00
Li Tian
ce747b8b8e wsl-oobe.sh: Ask for re-input of username when error
Ask for re-input when username either is invalid or exists.

Signed-off-by: Li Tian <litian@redhat.com>
2025-10-14 17:19:19 +00:00
Li Tian
9a77cca64b wsl-setup: fix --help|-h option error prompt
--help|-h ought not to fall into error prompt.

Signed-off-by: Li Tian <litian@redhat.com>
2025-10-14 17:19:19 +00:00
Li Tian
c937ddd38f tmpfiles: not forcefully create symlink /tmp/.X11-unix
In RHEL/CentOS, the X11 socket is created in /tmp fine.
Do not forcefully create it which cause an error during
installation using dnf/yum.

Signed-off-by: Li Tian <litian@redhat.com>
2025-09-23 12:44:41 +08:00
Jeremy Cline
2a67afb554 Merge #13 oobe: ignore cloud-init warnings 2025-08-12 12:52:24 +00:00
Fedora Release Engineering
c6758f12f1 Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild 2025-07-25 20:33:43 +00:00
Simon de Vlieger
bbafa4924c
oobe: ignore cloud-init warnings
`cloud-init` features multiple different non-zero exit codes [1]. Most
importantly it can return `2` for recoverable errors.

This happens commonly in RHEL land where WSL images currently contain,
and enable `cloud-init`. When the user does not provide a WSL data
source (configures their host) then the fallback data source of `None`
is used by `cloud-init`. This emits a warning and thus `cloud-init`
returns a non-zero exit status.

Let's ignore any exit code that isn't `1` (critical). If there *was* a
critical error we now also show the error message contained in
`cloud-init status`.

[1]: https://docs.cloud-init.io/en/latest/explanation/failure_states.html#cloud-init-error-codes

Signed-off-by: Simon de Vlieger <supakeen@redhat.com>
2025-07-11 11:43:43 +02:00
Troy Dawson
b879d40631 Fix script arguments section
Signed-off-by: Troy Dawson <tdawson@redhat.com>
2025-07-07 13:39:46 -07:00
Jeremy Cline
ef26ebb240
oobe: don't append the user section to /etc/wsl.conf
Doing this apparently[0] breaks using `wsl --manage <distro>
--set-default-user` (in my test, wsl says it completed successfully, but
actually doesn't do anything at all). Since we set the default UID in
wsl-distribution.conf, the default default user will be UID 1000, which
we expect to create anyway.

While it's nice to support old versions of WSL, I think it's also
reasonable to require users to update to ensure things work. For
example, most things in Fedora expect cgroups v2, but WSL only removed
cgroups v1 in 2.5.

If users report an issue and note they're not using the latest WSL
stable release I'm just going to tell them to reproduce it on the
latest, and if they can't I'm not going to spend any time trying to make
it work.

[0] https://github.com/microsoft/WSL/pull/13094#issuecomment-2971990351

Signed-off-by: Jeremy Cline <jeremycline@linux.microsoft.com>
2025-07-07 09:44:57 -04:00
Jeremy Cline
99ab88e361
Add Requires for utilities used in the OOBE script
The OOBE script uses adduser from the shadow-utils package and
systemctl to inspect service state, so we should require those be
installed. This is particularly important for users building custom WSL
images since we explicitly list both those packages in our Kiwi config.

Suggested-by: Simon de Vlieger <supakeen@redhat.com>
Signed-off-by: Jeremy Cline <jeremycline@linux.microsoft.com>
2025-07-01 10:48:13 -04:00
Simon de Vlieger
fc30a377e8
oobe: wait for cloud-init to finish
Let's wait for `cloud-init` to finish before we exit the OOBE; this
ensures that any potential user has been created. In the future we might
want to always continue with our OOBE, in those cases that `cloud-init`
didn't create a user we can then continue with the prompt(s).

Signed-off-by: Simon de Vlieger <supakeen@redhat.com>
2025-06-18 21:52:05 +02:00
Simon de Vlieger
3ee41192ed
oobe: message for enabled cloud-init
Show a message when cloud-init is enabled so users know what is going
on.

Signed-off-by: Simon de Vlieger <supakeen@redhat.com>
2025-06-05 16:50:38 +02:00
Simon de Vlieger
5afaf63d99
oobe: exit early for cloud-init
WSL supports `cloud-init` for provisioning. In some cases (RHEL) this is
enabled. If `wsl-setup` is used on RHEL then there's a TOCTOU between
the check for "no user exists" and the "create user" part as
`cloud-init` creates the user during the prompt.

Let's exit early and assume everything is handled by `cloud-init` *if*
it is enabled.

Signed-off-by: Simon de Vlieger <supakeen@redhat.com>
2025-05-28 12:01:25 +02:00
13 changed files with 328 additions and 1 deletions

0
.gitignore vendored Normal file
View file

20
LICENSE Normal file
View file

@ -0,0 +1,20 @@
Copyright 2025 Fedora Project Authors.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# wsl-setup
The wsl-setup package

View file

@ -1 +0,0 @@
Added to RHEL 9.7 rhbz#2374941

2
firstboot-override.conf Normal file
View file

@ -0,0 +1,2 @@
[Unit]
ConditionVirtualization=!wsl

0
sources Normal file
View file

23
wsl-distribution.conf Normal file
View file

@ -0,0 +1,23 @@
# The /etc/wsl-distribution.conf configuration file.
#
# This is not intended to be edited by users; it is how WSL discovers
# distribution defaults.
#
# Available configuration options are documented at
# https://learn.microsoft.com/en-us/windows/wsl/build-custom-distro
[oobe]
# Command run the first time the user opens an interactive shell.
# If the command returns non-zero, it is considered unsuccessful and the
# user won't be able to open a shell.
command = /usr/libexec/wsl/oobe.sh
# Default UID for user the distribution starts with.
defaultUid = 1000
# Default name the distribution is registered under.
# This is used when the user double-clicks to install, or uses
# wsl --install --from-file ./Fedora.wsl
defaultName = DEFAULT_NAME
[shortcut]
enabled = true
icon = DEFAULT_ICON_FULL_PATH

94
wsl-oobe.sh Normal file
View file

@ -0,0 +1,94 @@
#!/bin/bash
# The Fedora WSL out of box experience script.
#
# This command runs the first time the user opens an interactive shell if
# `cloud-init` is not enabled.
#
# A non-zero exit code indicates to WSL that setup failed.
set -ueo pipefail
DEFAULT_USER_ID=1000
function create_user() {
local rc=0
while true; do
read -r -p "Create a default Unix user account: " username
# Create the user.
rc=$(
set +e
/usr/sbin/useradd -m -G wheel --uid "$DEFAULT_USER_ID" "$username" > /dev/null
echo $?
)
case $rc in
# 3: invalid argument to option
# 19: Bad login name (since Fedora 42)
3 | 19)
echo "Invalid username. A valid username must start with a letter or underscore, and can contain letters, digits, underscores, dots, dashes and a dollar sign at the end."
continue
;;
# 9: username or group name already in use
9)
echo "User \"$username\" already exists"
continue
;;
0)
break
;;
*)
echo "Unexpected error code from useradd: $rc"
break
;;
esac
done
}
# When `cloud-init` is enabled it might take care of user creation and other bits, depending on its
# configuration contained within the WSL image; or the WSL configuration as provided by the host.
if systemctl is-enabled cloud-init.service > /dev/null ; then
echo 'cloud-init is enabled, skipping user account creation. Waiting for cloud-init to finish.'
# We need to run cloud-init in a sub-shell that disables errexit so we can inspect its error code
# Without the script exiting.
(set +e cloud-init status --wait > /dev/null 2>&1)
cloud_status=$?
# We only exit unsuccesfully on a cloud-init exit status of 1. This means an unrecoverable error,
# and the system might not be usable. Any other exit status (0 for success, or 2 for warning) can
# be ignored and happens commonly, for example when there is a default configuration but the fallback
# data source was used.
if [ "${cloud_status}" -eq 1 ]; then
echo 'cloud-init failed unrecoverably. Failed to provision system.'
cloud-init status --long
exit 1
fi
exit 0
fi
if getent passwd $DEFAULT_USER_ID > /dev/null ; then
echo 'User account already exists, skipping creation'
exit 0
fi
echo 'Please create a default user account. The username does not need to match your Windows username.'
echo 'For more information visit: https://aka.ms/wslusers'
create_user
cat > /etc/sudoers.d/wsluser << EOF
# Ensure the WSL initial user can use sudo without a password.
#
# Since the user is in the wheel group, this file can be removed
# if you wish to require a password for sudo. Be sure to set a
# user password before doing so with 'sudo passwd $username'!
$username ALL=(ALL) NOPASSWD: ALL
EOF
echo 'Your user has been created, is included in the wheel group, and can use sudo without a password.'
echo "To set a password for your user, run 'sudo passwd $username'"

96
wsl-setup Executable file
View file

@ -0,0 +1,96 @@
#!/usr/bin/bash
#
# Setup the environment for the new WSL configuration
#
# Copyright (C) 2025
# SPDX-License-Identifier: MIT
#
# Authors:
# Troy Dawson <tdawson@redhat.com>
#
###############
# Variables
###############
DISTRIBUTION_TEMPLATE_FILE="/usr/share/wsl-setup/wsl-distribution.conf.template"
DISTRIBUTION_CONF_FILE="/usr/lib/wsl-distribution.conf"
DISTRIBUTION_CONF_LINK="/etc/wsl-distribution.conf"
. /etc/os-release
DEFAULT_NAME="${NAME// /}-${VERSION_ID%.*}"
ICON_PATH="/usr/share/pixmaps/fedora-logo.ico"
###############
# Show help
###############
usage() {
echo "Usage `basename $0` <options> " >&2
echo >&2
echo "Setup the environment for the new WSL configuration" >&2
echo >&2
echo "Options:" >&2
echo " --name, -n" >&2
echo " Set the distro name" >&2
echo " Default: ${DEFAULT_NAME}" >&2
echo " --icon, -i" >&2
echo " Full pathname to the icon" >&2
echo " Default: ${ICON_PATH}" >&2
echo " --help, -h" >&2
echo " Show this options menu" >&2
echo >&2
popd &>/dev/null
exit 1
}
###############
# Get our arguments
###############
while [[ "$#" -ge 1 ]]
do
key="$1"
case $key in
--name | -n )
if ! [ "${2}" == "" ] ; then
DEFAULT_NAME="${2}"
shift
else
echo
echo "ERROR: Name is not provided"
echo
usage
exit 2
fi
;;
--icon | -i )
if ! [ "${2}" == "" ] ; then
ICON_PATH="${2}"
shift
else
echo
echo "ERROR: Icon full path is not provided"
echo
usage
exit 2
fi
;;
--help | -h )
usage
exit 0
;;
* )
echo
echo "ERROR BAD OPTION: $key"
echo
usage
exit 2
;;
esac
shift
done
###############
# Do the work
###############
cp -f ${DISTRIBUTION_TEMPLATE_FILE} ${DISTRIBUTION_CONF_FILE}
sed -i -e "s|DEFAULT_NAME|${DEFAULT_NAME}|" -e "s|DEFAULT_ICON_FULL_PATH|${ICON_PATH}|" ${DISTRIBUTION_CONF_FILE}

1
wsl-setup-tmpfiles.conf Normal file
View file

@ -0,0 +1 @@
L /tmp/.X11-unix - - - - /mnt/wslg/.X11-unix

View file

@ -0,0 +1,3 @@
L+ /run/user/%U/wayland-0.lock - - - - /mnt/wslg/runtime-dir/wayland-0.lock
L+ /run/user/%U/wayland-0 - - - - /mnt/wslg/runtime-dir/wayland-0
L+ /run/user/%U/pulse - - - - /mnt/wslg/runtime-dir/pulse

82
wsl-setup.spec Normal file
View file

@ -0,0 +1,82 @@
Name: wsl-setup
Version: 1.0.1
Release: %autorelease
Summary: Windows Subsystem for Linux setup script and configuration
License: MIT
URL: https://src.fedoraproject.org/rpms/wsl-setup
BuildArch: noarch
Source1: LICENSE
Source2: wsl.conf
Source3: wsl-distribution.conf
Source4: wsl-oobe.sh
Source5: firstboot-override.conf
Source6: wsl-setup-tmpfiles.conf
Source7: wsl-setup-user-tmpfiles.conf
Source8: wsl-setup
BuildRequires: systemd-rpm-macros
# Needed for the distribution icon
Requires: system-logos
# Utilities used by the OOBE script
Requires: shadow-utils
Requires: systemd
%description
Provides WSL specific configuration files and first-time setup script.
%prep
%build
%install
install -pm 0644 %{SOURCE1} LICENSE
install -Dpm0644 -t %{buildroot}%{_sysconfdir}/ %{SOURCE2}
install -Dpm0644 -T %{SOURCE3} %{buildroot}%{_datarootdir}/wsl-setup/wsl-distribution.conf.template
install -Dpm0755 -T %{SOURCE4} %{buildroot}%{_libexecdir}/wsl/oobe.sh
install -Dpm0755 -T %{SOURCE8} %{buildroot}%{_bindir}/wsl-setup
ln -s ..%{_prefix}/lib/wsl-distribution.conf %{buildroot}%{_sysconfdir}/wsl-distribution.conf
# WSL provides a socket for x11, but we need to ensure its linked to in /tmp.
# The official recommendation is to disable tmpfiles entirely, but it would be
# nice to work with it, instead.
# https://learn.microsoft.com/en-us/windows/wsl/build-custom-distro#systemd-recommendations
install -Dpm0644 %{SOURCE6} %{buildroot}%{_tmpfilesdir}/%{name}.conf
# WSL provides a Wayland and PulseAudio socket as well, which are expected to be in
# the user's runtime directory. This configuration sets up the links for each user.
install -Dpm0644 %{SOURCE7} %{buildroot}%{_user_tmpfilesdir}/%{name}.conf
# Currently systemd-firstboot hangs forever attempting to acquire the console; this is
# problematic since many other services wait for it to complete before starting, including
# things like the system D-Bus. Configure it to not run in WSL (a preset didn't seem to work)
# until we can see about adjusting either WSL or systemd to make it behave.
install -Dpm0644 %{SOURCE5} %{buildroot}%{_unitdir}/systemd-firstboot.service.d/override.conf
%post
# generate the "auto" naming, using the defaults
%{_bindir}/wsl-setup
%files
%{_bindir}/wsl-setup
%config(noreplace) %{_sysconfdir}/wsl.conf
%ghost %attr(644, root, root) %{_prefix}/lib/wsl-distribution.conf
%{_sysconfdir}/wsl-distribution.conf
%dir %{_datarootdir}/wsl-setup/
%{_datarootdir}/wsl-setup/wsl-distribution.conf.template
%{_libexecdir}/wsl/oobe.sh
%{_tmpfilesdir}/%{name}.conf
%{_user_tmpfilesdir}/%{name}.conf
%{_unitdir}/systemd-firstboot.service.d/override.conf
%license LICENSE
%changelog
%autochangelog

4
wsl.conf Normal file
View file

@ -0,0 +1,4 @@
# Refer to https://learn.microsoft.com/en-us/windows/wsl/wsl-config#wslconf
# for the full set of configuration options.
[boot]
systemd=true