Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 53 additions & 20 deletions public/wsl2.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Development Environment | AlmaLinux 10 on WSL 2"
description: "AlmaLinux 10 on WSL 2 for a RHEL-compatible local stack. One Ansible playbook installs PHP, Apache, MariaDB, Composer, Node.js and phpMyAdmin, and provisions a virtualhost for every project you add."
description: "AlmaLinux 10 on WSL 2 for a RHEL-compatible local stack. One Ansible playbook installs PHP, Apache, MariaDB, Composer, Node.js and phpMyAdmin, and a second provisions a virtualhost for every project you add."
canonical_url: "https://www.dotkernel.com/wsl2/"
language: "en"
---
Expand Down Expand Up @@ -30,7 +30,8 @@ Terminal -> WSL 2 -> AlmaLinux -> Ansible -> Ready.
AlmaLinux is a RHEL-compatible distribution, so the packages, package manager and service conventions you use locally - `dnf`, `systemd` and the rest - are the ones you will see again in staging and production.
WSL 2 puts that distro on a Windows machine without a second computer or a Windows-native rebuild of every tool.

Everything here also runs the same way without WSL, directly on a bare AlmaLinux 10 host - the Ansible playbooks do not know or care which one they are provisioning.
Everything from Setup Packages onwards also runs on a bare AlmaLinux 10 host without WSL - the Ansible playbooks do not know or care which one they are provisioning.
Connect over SSH, and use the server's IP address instead of `localhost` when you test it.

- RHEL-compatible, matches production
- One playbook, the whole stack
Expand All @@ -39,15 +40,16 @@ Everything here also runs the same way without WSL, directly on a bare AlmaLinux

## Three steps to a running shell

Each step runs in a different place - Windows Terminal for the first two, the AlmaLinux 10 shell for the third.
Steps 1 and 2 run in Windows Terminal and step 3 in the AlmaLinux 10 shell; step 2 ends inside the new distro with a quick systemd check.
The full walkthrough, prompts and all, is in the docs.

### 1 . Terminal & requirements

Install Windows Terminal, then confirm WSL 2 is enabled - Hyper-V, Virtual Machine Platform and Windows Subsystem for Linux, all turned on in Windows features.
On Windows 11, install Windows Terminal, then check for a modern WSL 2 install.
If `wsl --version` isn't recognized, install WSL 2 with `wsl --install --no-distribution` and restart when prompted.

```shell
wsl -v
wsl --version
```

### 2 . Install AlmaLinux 10
Expand All @@ -58,15 +60,25 @@ Stop any other running distro, then install AlmaLinux 10 and create your Unix us
wsl --install -d AlmaLinux-10
```

Before moving on, confirm systemd is active inside AlmaLinux 10 - the playbook needs it.
If the check below prints an error instead of a status, add `systemd=true` under `[boot]` in `/etc/wsl.conf`, run `wsl --shutdown` from Windows Terminal and reopen the distro.

```shell
systemctl is-system-running
```

### 3 . Setup packages

Clone `dotkernel/development`, fill in `config.yml` with your Git identity and MariaDB root password, and let Ansible provision the rest.
Inside AlmaLinux 10, update the system, add the EPEL and Remi repositories, and install `ansible-core` with the `community.general` and `community.mysql` collections.
Then clone the `alma-linux-10` branch of `dotkernel/development`, copy `wsl/config.yml.dist` to `config.yml`, fill in your Git identity and MariaDB root password, and run the playbook from `development/wsl`.

```shell
ansible-playbook -i hosts install.yml --ask-become-pass
```

Not using WSL? Skip straight to Setup Packages on a bare AlmaLinux 10 host - the same playbook runs there unchanged.
Not using WSL? Skip straight to Setup Packages on a bare AlmaLinux 10 host - the same playbook runs there unchanged; test it with the server's IP address instead of `localhost`.

After setup, [Editor Integration](https://docs.dotkernel.org/development/v2/editor-integration/) connects VS Code or PhpStorm, and [WSL Configuration](https://docs.dotkernel.org/development/v2/wsl-configuration/) covers where to keep projects and how to cap WSL's memory and CPU.

## What one playbook installs

Expand All @@ -75,36 +87,41 @@ Not using WSL? Skip straight to Setup Packages on a bare AlmaLinux 10 host - the
| Component | What you get |
| --- | --- |
| Web server | Apache, with virtualhosts routed automatically under `*.localhost`. |
| Database | MariaDB 11.4 LTS, plus phpMyAdmin for browsing it. |
| PHP | 8.4 by default via the Remi repository; `php81` … `php85` aliases switch versions. |
| Database | MariaDB 12.3 from the MariaDB repository, plus phpMyAdmin for browsing it. |
| PHP | 8.5 by default via the Remi repository; `php81` … `php85` aliases switch versions. |
| Node.js | 22 by default via NodeSource; `node18` … `node24` aliases switch versions. |
| Git & Composer | Your Git identity from `config.yml`, and the latest Composer, kept current with `composer self-update`. |
| Ansible | `community.general` and `community.mysql` collections - the same tool that just installed itself. |
| Git & Composer | Your Git identity from `config.yml`, and the latest Composer at install time; update it later with `composer self-update`. |

## Every project, its own subdomain

`api.dotkernel.localhost` and `frontend.dotkernel.localhost` can point at two different projects on the same machine, and Apache routes both without a single edit to the Windows hosts file - any `*.localhost` domain is routed automatically.

List the domains you want under `config.yml`'s `virtualhosts` key and run the playbook.
List the domains you want under `config.yml`'s `virtualhosts` key and run `create-virtualhost.yml` - a separate playbook you re-run for every new project, without repeating `install.yml`.
Existing entries are left untouched, so you keep adding to the same file as your project grows.

- [Read the virtualhosts docs](https://docs.dotkernel.org/development/v2/virtualhosts/overview/)

### One playbook, every domain

In `development/wsl/config.yml`, under `virtualhosts`:
In `development/wsl/config.yml`, under `config.virtualhosts`:

```text
api.dotkernel.localhost
```yaml
config:
virtualhosts:
- "api.dotkernel.localhost"
Comment thread
bidi47 marked this conversation as resolved.
```

`api.dotkernel.localhost` is only an example - use any name your project needs, such as `laravel.localhost` or `shop.localhost`, as long as it ends in `.localhost` and uses only lowercase letters, numbers and hyphens.
Add one list item per project.

Then provision it:

```shell
ansible-playbook -i hosts create-virtualhost.yml --ask-become-pass
```

Files go under `/var/www/api.dotkernel.localhost/html`, with the document root at `html/public`.
Files go under `/var/www/<your-domain>/html` - for example `/var/www/api.dotkernel.localhost/html` - with the document root at `html/public`.
`html/public` doesn't exist until you place a project there, so the URL shows an error until then.

## Common questions

Expand All @@ -121,10 +138,11 @@ Use one of the predefined aliases - `node18`, `node20`, `node22` or `node24` - w
### How do I fix permission issues?

Local development only: `chmod -R 777 data`, `log` or `public/uploads`, whichever directory the error names.
Don't carry this into staging or production.

### Where are the error logs?

Apache: `/var/log/httpd/error_log`. PHP-FPM: `/var/log/php-fpm/error.log` and `www-error.log`.
Apache: `/var/log/httpd/error_log`, plus `/var/www/<virtualhost>/log/error.log` for each virtualhost. PHP-FPM: `/var/log/php-fpm/error.log` and `www-error.log`.

### How do I update Composer?

Expand All @@ -138,14 +156,29 @@ Add `alias name="command"` to `.bash_profile` in your home directory, then run i

Remove its folder under `/var/www/`, its Apache config and enabled-site symlink, then `sudo systemctl restart httpd`.

### Why does the playbook fail with a systemd error?

systemd isn't active in the distro yet.
Add `systemd=true` under `[boot]` in `/etc/wsl.conf`, run `wsl --shutdown` from Windows Terminal, reopen AlmaLinux 10 and re-run `install.yml`.

### What if port 80 is already in use?

Find the Windows service holding it with `netstat -ano | findstr :80` and stop it, or change Apache's `Listen` port in `/etc/httpd/conf/httpd.conf` and restart httpd.

### Is this environment safe to expose beyond localhost?

No. It is for local development only: the MariaDB root password is stored in plaintext, phpMyAdmin allows root login and the firewall is off by default.

### Can I run this without WSL?

Yes - every instruction here works the same way on a bare AlmaLinux 10 host.
Yes - from Setup Packages onwards the steps are the same on a bare AlmaLinux 10 host.
Skip the WSL steps, connect over SSH, and use the server's IP address instead of `localhost`.

## Provision once, match production everywhere.
## Provision once, match your production OS

Built for how the platform ships.

The WSL 2 + AlmaLinux 10 setup is maintained by the same team behind the rest of the Headless Platform, so the local environment stays in step with what actually runs in production - not a Docker approximation of it.
The WSL 2 + AlmaLinux 10 setup is maintained by the same team behind the rest of the Headless Platform, so the local environment stays on the same OS family as production - not a Docker approximation of it.
It is a local development environment only: security is relaxed by default, so never expose it to a network.

[Talk to us ->](https://www.dotkernel.com/contact/)
Loading