Compare commits

...
Sign in to create a new pull request.

15 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
Troy Dawson
0479b8395c Change /usr/lib/wsl-distribution.conf to a ghost file
Signed-off-by: Troy Dawson <tdawson@redhat.com>
2025-05-19 08:37:51 -07:00
Troy Dawson
b781149120 Make wsl-setup a script
The script generates wsl-distribution.conf from a template.
You can pass it options for the Name as well as the
logo file.

Signed-off-by: Troy Dawson <tdawson@redhat.com>
2025-05-19 08:37:42 -07:00
5 changed files with 175 additions and 24 deletions

View file

@ -20,4 +20,4 @@ defaultName = DEFAULT_NAME
[shortcut]
enabled = true
icon = /usr/share/pixmaps/fedora-logo.ico
icon = DEFAULT_ICON_FULL_PATH

View file

@ -2,7 +2,8 @@
# The Fedora WSL out of box experience script.
#
# This command runs the first time the user opens an interactive shell.
# 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.
@ -10,19 +11,75 @@ set -ueo pipefail
DEFAULT_USER_ID=1000
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'
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
# Prompt from the username
read -r -p 'Enter new UNIX username: ' username
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 the user
/usr/sbin/useradd -m -G wheel --uid $DEFAULT_USER_ID "$username"
create_user
cat > /etc/sudoers.d/wsluser << EOF
# Ensure the WSL initial user can use sudo without a password.
@ -33,13 +90,5 @@ cat > /etc/sudoers.d/wsluser << EOF
$username ALL=(ALL) NOPASSWD: ALL
EOF
# Set the default user; necessary when this script is manually run in versions
# of WSL prior to 2.4.
cat >> /etc/wsl.conf << EOF
[user]
default = "$username"
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}

View file

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

View file

@ -1,5 +1,5 @@
Name: wsl-setup
Version: 1.0.0
Version: 1.0.1
Release: %autorelease
Summary: Windows Subsystem for Linux setup script and configuration
License: MIT
@ -13,12 +13,16 @@ 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.
@ -33,8 +37,9 @@ Provides WSL specific configuration files and first-time setup script.
%install
install -pm 0644 %{SOURCE1} LICENSE
install -Dpm0644 -t %{buildroot}%{_sysconfdir}/ %{SOURCE2}
install -Dpm0644 -t %{buildroot}%{_prefix}/lib/ %{SOURCE3}
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.
@ -55,16 +60,17 @@ install -Dpm0644 %{SOURCE5} %{buildroot}%{_unitdir}/systemd-firstboot.service.d/
%post
# generate the "auto" naming
. %{_sysconfdir}/os-release
DYNAMIC_NAME="${NAME// /}-${VERSION_ID%.*}"
sed -i "s,DEFAULT_NAME,${DYNAMIC_NAME}," %{_sysconfdir}/wsl-distribution.conf
# generate the "auto" naming, using the defaults
%{_bindir}/wsl-setup
%files
%{_bindir}/wsl-setup
%config(noreplace) %{_sysconfdir}/wsl.conf
%{_prefix}/lib/wsl-distribution.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