Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit 36bd28d

Browse files
karmendraKarmendra Suthar
andauthored
WSL Installation Upgrades and Documentation (#1958)
* WSL Installation Upgrades and Documentation - bin/homestead - Registered WslApplyFolderMapping command - scripts\features\mariadb.sh - stop the mysql service before uninstall and remove the installation tracking file. - scripts\features\mysql.sh - Create feature installation script for mysql. - scripts\features\postgresql.sh - removed `systemctl disable postgresq` from the end to make sure it works after the feature install - src\WslApplyFeatures.php - Changed the command name from wsl:apply-features to wsl:features. - src\WslApplyFolderMapping.php - Added new command to do folder mapping - src\WslCreateDatabaseCommand.php - Changed the command name from wsl:create-databases to wsl:databases. - src\WslCreateSiteCommand.php - Changed the command name from wsl:create-sites to wsl:sites. - Remove nginx/sites-enabled/* as well while removing existing nginx sites. - Add cron job for laravel schedule:run if mentioned in yaml file. - wsl.md - Documentation for Installing Homestead on Windows subsystem for Linux * Style CI Fix * Fixed a typo * Added validations for WSL_USER_NAME and WSL_USER_GROUP --------- Co-authored-by: Karmendra Suthar <karmendra.suthar@omniware.in>
1 parent 219e126 commit 36bd28d

File tree

10 files changed

+510
-16
lines changed

10 files changed

+510
-16
lines changed

bin/homestead

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ $app = new Symfony\Component\Console\Application('Laravel Homestead', '15.0.2');
1212

1313
$app->add(new Laravel\Homestead\MakeCommand);
1414
$app->add(new Laravel\Homestead\WslApplyFeatures);
15+
$app->add(new Laravel\Homestead\WslApplyFolderMapping);
1516
$app->add(new Laravel\Homestead\WslCreateSiteCommand);
1617
$app->add(new Laravel\Homestead\WslCreateDatabaseCommand());
1718

bin/wsl-init

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,67 @@
55
##################################
66
export DEBIAN_FRONTEND=noninteractive
77

8-
echo "What is your WSL user name?"
8+
echo "Changing current working directory to Homestead directory..."
9+
cd "$(dirname "$0")/.."
10+
11+
if [[ $EUID -ne 0 ]]; then
12+
echo "Error: This script must be run as root.">&2
13+
14+
exit 1
15+
fi
16+
17+
UNAME=$(lsb_release -is)
18+
if [[ "$UNAME" != "Ubuntu" ]]; then
19+
echo "Error: WSL Homestead only supports Ubuntu Distro">&2
20+
21+
exit 1
22+
fi
23+
UBUNTU_VERSION=$(lsb_release -rs)
24+
if [[ "$UBUNTU_VERSION" != "20.04" && "$UBUNTU_VERSION" != "22.04" ]]; then
25+
echo "Error: WSL Homestead only supports Ubuntu 20.04 and 22.04.">&2
26+
27+
exit 1
28+
fi
29+
30+
if [[ -f /root/.homestead-provisioned ]]; then
31+
echo "Error: This server has already been provisioned by Laravel Homestead." >&2
32+
echo "If you need to re-provision, you may remove the /root/.homestead-provisioned file and try again." >&2
33+
34+
exit 1
35+
fi
36+
echo "Starting..."
37+
38+
echo "What is your WSL user name? [vagrant]: "
939
read WSL_USER_NAME
1040

11-
echo "What is your WSL user group? (Same as username if you're unsure)"
41+
echo "What is your WSL user group? (Same as username if you're unsure) [vagrant]: "
1242
read WSL_USER_GROUP
1343

44+
# Set default
45+
if [ -z "${WSL_USER_NAME}" ]; then
46+
WSL_USER_NAME=vagrant
47+
fi
48+
if [ -z "${WSL_USER_GROUP}" ]; then
49+
WSL_USER_GROUP=vagrant
50+
fi
51+
52+
# Validate user and group
53+
if ! id "$WSL_USER_NAME" &>/dev/null; then
54+
echo "Error: User $WSL_USER_NAME does not exist.">&2
55+
56+
exit 1
57+
fi
58+
if ! getent group "$WSL_USER_GROUP" &>/dev/null; then
59+
echo "Error: Group $WSL_USER_GROUP does not exist.">&2
60+
61+
exit 1
62+
fi
63+
if ! groups "$WSL_USER_NAME" | grep -q "\b$WSL_USER_GROUP\b"; then
64+
echo "Error: User $WSL_USER_NAME is not a member of group $WSL_USER_GROUP.">&2
65+
66+
exit 1
67+
fi
68+
1469
# Save necessary information for features
1570
mkdir -p ~/.homestead-features
1671
mkdir -p /home/$WSL_USER_NAME/.homestead-features

scripts/features/mariadb.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ chown -Rf $WSL_USER_NAME:$WSL_USER_GROUP /home/$WSL_USER_NAME/.homestead-feature
2323
service apparmor stop
2424
update-rc.d -f apparmor remove
2525

26+
# Stop MySQL service
27+
service mysql stop
2628
# Remove MySQL
2729
apt-get -o Dpkg::Options::="--force-confnew" remove -y --purge mysql-server mysql-client
2830
apt-get autoremove -y
@@ -31,6 +33,7 @@ apt-get autoclean
3133
rm -rf /var/lib/mysql/*
3234
rm -rf /var/log/mysql
3335
rm -rf /etc/mysql
36+
rm -r /home/$WSL_USER_NAME/.homestead-features/mysql
3437

3538
# Determine version from config
3639
set -- "$1"
@@ -44,6 +47,7 @@ else
4447
sudo bash mariadb_repo_setup --mariadb-server-version="$version"
4548
echo "MariaDB specific target version : $version"
4649
fi
50+
apt-get update
4751

4852
debconf-set-selections <<< "mariadb-server mysql-server/data-dir select ''"
4953
debconf-set-selections <<< "mariadb-server mysql-server/root_password password secret"

scripts/features/mysql.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env bash
2+
3+
if [ -f ~/.homestead-features/wsl_user_name ]; then
4+
WSL_USER_NAME="$(cat ~/.homestead-features/wsl_user_name)"
5+
WSL_USER_GROUP="$(cat ~/.homestead-features/wsl_user_group)"
6+
else
7+
WSL_USER_NAME=vagrant
8+
WSL_USER_GROUP=vagrant
9+
fi
10+
11+
export DEBIAN_FRONTEND=noninteractive
12+
13+
if [ -f /home/$WSL_USER_NAME/.homestead-features/mysql ]; then
14+
echo "Mysql already installed."
15+
exit 0
16+
fi
17+
18+
touch /home/$WSL_USER_NAME/.homestead-features/mysql
19+
chown -Rf $WSL_USER_NAME:$WSL_USER_GROUP /home/$WSL_USER_NAME/.homestead-features
20+
21+
# Stop MariDB service
22+
service mariadb stop
23+
# Remove old PPA
24+
rm -f /etc/apt/sources.list.d/mariadb.list*
25+
# Remove MariaDB
26+
apt-get -o Dpkg::Options::="--force-confnew" remove -y --purge mariadb-server mariadb-client mysql-common
27+
apt-get autoremove -y
28+
apt-get autoclean
29+
30+
rm -rf /var/lib/mysql/*
31+
rm -rf /var/log/mysql
32+
rm -rf /etc/mysql
33+
rm -r /home/$WSL_USER_NAME/.homestead-features/mariadb
34+
35+
# Install MySQL
36+
echo "mysql-server mysql-server/root_password password secret" | debconf-set-selections
37+
echo "mysql-server mysql-server/root_password_again password secret" | debconf-set-selections
38+
apt-get install -y mysql-server
39+
40+
# Configure MySQL 8 Remote Access and Native Pluggable Authentication
41+
mkdir -p /etc/mysql/conf.d
42+
cat > /etc/mysql/conf.d/mysqld.cnf << EOF
43+
[mysqld]
44+
bind-address = 0.0.0.0
45+
disable_log_bin
46+
default_authentication_plugin = mysql_native_password
47+
EOF
48+
49+
# Configure MySQL Password Lifetime
50+
echo "default_password_lifetime = 0" >> /etc/mysql/mysql.conf.d/mysqld.cnf
51+
52+
# Configure MySQL Remote Access
53+
sed -i '/^bind-address/s/bind-address.*=.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
54+
service mysql restart
55+
56+
export MYSQL_PWD=secret
57+
58+
mysql --user="root" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'secret';"
59+
mysql --user="root" -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;"
60+
mysql --user="root" -e "CREATE USER 'homestead'@'0.0.0.0' IDENTIFIED BY 'secret';"
61+
mysql --user="root" -e "CREATE USER 'homestead'@'%' IDENTIFIED BY 'secret';"
62+
mysql --user="root" -e "GRANT ALL PRIVILEGES ON *.* TO 'homestead'@'0.0.0.0' WITH GRANT OPTION;"
63+
mysql --user="root" -e "GRANT ALL PRIVILEGES ON *.* TO 'homestead'@'%' WITH GRANT OPTION;"
64+
mysql --user="root" -e "FLUSH PRIVILEGES;"
65+
mysql --user="root" -e "CREATE DATABASE homestead character set UTF8mb4 collate utf8mb4_bin;"
66+
67+
sudo tee /home/${WSL_USER_NAME}/.my.cnf <<EOL
68+
[mysqld]
69+
character-set-server=utf8mb4
70+
collation-server=utf8mb4_bin
71+
EOL
72+
73+
service mysql restart
74+
75+
unset MYSQL_PWD

scripts/features/postgresql.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,3 @@ echo "host all all 10.0.2.2/32 md5" | t
3535

3636
sudo -u postgres /usr/bin/createdb --echo --owner=homestead homestead
3737
service postgresql restart
38-
# Disable to lower initial overhead
39-
systemctl disable postgresql

src/WslApplyFeatures.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class WslApplyFeatures extends Command
1515
use GeneratesSlugs;
1616

1717
/**
18-
* The base path of the Laravel installation.
18+
* The base path of the Homestead installation.
1919
*
2020
* @var string
2121
*/
@@ -55,7 +55,7 @@ protected function configure()
5555
$this->featuresPath = getcwd().'/scripts/features';
5656

5757
$this
58-
->setName('wsl:apply-features')
58+
->setName('wsl:features')
5959
->setDescription('Configure features in WSL from Homestead configuration')
6060
->addOption('json', null, InputOption::VALUE_NONE, 'Determines if the Homestead settings file will be in json format.');
6161
}
@@ -77,9 +77,9 @@ public function execute(InputInterface $input, OutputInterface $output)
7777
$feature_cmd = '';
7878
$feature_name = array_key_first($feature);
7979
$feature_variables = $feature[$feature_name];
80-
80+
$output->writeln(PHP_EOL.($feature[$feature_name] ? '' : 'Not ').'Configuring feature: '.$feature_name);
8181
if ($feature_variables !== false) {
82-
$feature_path = "{$this->featuresPath}/{$feature_name}.sh > ~/.homestead-features/{$feature_name}.log";
82+
$feature_path = "{$this->featuresPath}/{$feature_name}.sh | tee ~/.homestead-features/{$feature_name}.log";
8383
// Prepare the feature variables if provided.
8484
if (is_array($feature_variables)) {
8585
$variables = join(' ', $feature_variables);
@@ -88,11 +88,11 @@ public function execute(InputInterface $input, OutputInterface $output)
8888
$feature_cmd = "sudo -E bash {$feature_path}";
8989
}
9090
shell_exec($feature_cmd);
91-
$output->writeln("Command output can be found via: sudo cat ~/.homestead-features/{$feature_name}.log");
91+
$output->writeln("Feature installation log can be found via: sudo cat ~/.homestead-features/{$feature_name}.log");
9292
}
9393
}
9494

95-
$output->writeln('WSL features have been configured!');
95+
$output->writeln(PHP_EOL.'WSL features have been configured!');
9696

9797
return 0;
9898
}

src/WslApplyFolderMapping.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace Laravel\Homestead;
4+
5+
use Laravel\Homestead\Settings\JsonSettings;
6+
use Laravel\Homestead\Settings\YamlSettings;
7+
use Symfony\Component\Console\Command\Command;
8+
use Symfony\Component\Console\Input\InputInterface;
9+
use Symfony\Component\Console\Input\InputOption;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
12+
class WslApplyFolderMapping extends Command
13+
{
14+
/**
15+
* Configure the command options.
16+
*
17+
* @return void
18+
*/
19+
protected function configure()
20+
{
21+
$this
22+
->setName('wsl:folders')
23+
->setDescription('Configure folder mapping in WSL from Homestead configuration')
24+
->addOption('json', null, InputOption::VALUE_NONE, 'Determines if the Homestead settings file will be in json format.');
25+
}
26+
27+
/**
28+
* Execute the command.
29+
*
30+
* @param InputInterface $input
31+
* @param OutputInterface $output
32+
* @return int
33+
*/
34+
public function execute(InputInterface $input, OutputInterface $output)
35+
{
36+
// Grab the current settings or create an example configuration
37+
$format = $input->getOption('json') ? 'json' : 'yaml';
38+
$settings = $this->parseSettingsFromFile($format, []);
39+
40+
foreach ($settings['folders'] as $key => $folder) {
41+
$folder_map = $folder['map'];
42+
$folder_to = $folder['to'];
43+
$parent_directory = dirname($folder_to);
44+
$folder_map_cmd = "rm -r {$folder_to} ; mkdir -p {$parent_directory} && ln -s {$folder_map} {$folder_to}";
45+
$out = shell_exec($folder_map_cmd);
46+
print_r($out);
47+
$output->writeln('Created symbolic link '.$folder_to.' to '.$folder_map.'.');
48+
}
49+
50+
$output->writeln('WSL folders have been mapped!');
51+
52+
return 0;
53+
}
54+
55+
/**
56+
* @param string $format
57+
* @param array $options
58+
* @return mixed
59+
*/
60+
protected function parseSettingsFromFile(string $format, array $options)
61+
{
62+
$SettingsClass = ($format === 'json') ? JsonSettings::class : YamlSettings::class;
63+
$filename = __DIR__."/../Homestead.{$format}";
64+
65+
return $SettingsClass::fromFile($filename)->toArray();
66+
}
67+
}

src/WslCreateDatabaseCommand.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected function configure()
4747
$this->defaultProjectName = $this->slug($this->projectName);
4848

4949
$this
50-
->setName('wsl:create-databases')
50+
->setName('wsl:databases')
5151
->setDescription('Create Databases in WSL from Homestead configuration')
5252
->addOption('json', null, InputOption::VALUE_NONE, 'Determines if the Homestead settings file will be in json format.');
5353
}
@@ -72,7 +72,7 @@ public function execute(InputInterface $input, OutputInterface $output)
7272
// run command to create the database
7373
$shell_output = shell_exec($create_cmd);
7474
if (! is_null($shell_output)) {
75-
var_dump($shell_output);
75+
print_r($shell_output);
7676
}
7777
}
7878
$output->writeln('WSL Databases have been created!');

src/WslCreateSiteCommand.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected function configure()
4747
$this->defaultProjectName = $this->slug($this->projectName);
4848

4949
$this
50-
->setName('wsl:create-sites')
50+
->setName('wsl:sites')
5151
->setDescription('Create Sites in WSL from Homestead configuration')
5252
->addOption('json', null, InputOption::VALUE_NONE, 'Determines if the Homestead settings file will be in json format.');
5353
}
@@ -62,7 +62,7 @@ protected function configure()
6262
public function execute(InputInterface $input, OutputInterface $output)
6363
{
6464
// Remove any existing nginx sites
65-
$shell_output = shell_exec('sudo rm -rf /etc/nginx/sites-available/*');
65+
$shell_output = shell_exec('sudo rm -rf /etc/nginx/sites-available/* /etc/nginx/sites-enabled/*');
6666
if (! is_null($shell_output)) {
6767
var_dump($shell_output);
6868
}
@@ -71,8 +71,9 @@ public function execute(InputInterface $input, OutputInterface $output)
7171
$format = $input->getOption('json') ? 'json' : 'yaml';
7272
$settings = $this->parseSettingsFromFile($format, []);
7373

74-
foreach ($settings['wsl_sites'] as $key => $site) {
74+
foreach ($settings['sites'] as $key => $site) {
7575
$type = $site['type'] ?? 'laravel';
76+
$output->writeln('Configuring site: '.$site['map'].' of type '.$type);
7677
$create_cmd = '';
7778
$headers = false;
7879
$rewrites = false;
@@ -94,7 +95,7 @@ public function execute(InputInterface $input, OutputInterface $output)
9495
$site['to'], // $1
9596
$site['port'] ?? 80, // $2
9697
$site['ssl'] ?? 443, // $3
97-
$site['php'] ?? '8.0', // $4
98+
$site['php'] ?? '8.3', // $4
9899
'', // $5 params
99100
$site['xhgui'] ?? '', // $6
100101
$site['exec'] ?? false, // $7
@@ -117,6 +118,22 @@ public function execute(InputInterface $input, OutputInterface $output)
117118
if (! is_null($shell_output)) {
118119
var_dump($shell_output);
119120
}
121+
122+
// run command to setup schedule cron
123+
if ($type == 'laravel' && ($site['schedule'] ?? false)) {
124+
$output->writeln('Configuring scheduler cron ...');
125+
$cron_cmd = "sudo -E bash {$this->basePath}/scripts/cron-schedule.sh {$site['map']} {$site['to']} {$args[4]}";
126+
$shell_output = shell_exec($cron_cmd);
127+
if (! is_null($shell_output)) {
128+
var_dump($shell_output);
129+
}
130+
} else {
131+
$no_cron_cmd = "sudo rm -f /etc/cron.d/{$site['map']}";
132+
$shell_output = shell_exec($no_cron_cmd);
133+
if (! is_null($shell_output)) {
134+
var_dump($shell_output);
135+
}
136+
}
120137
}
121138

122139
// Restart nginx

0 commit comments

Comments
 (0)