# How to Set Up and Run Licentia with WSL2 and Docker

This guide walks you through the entire process of installing WSL2 (Ubuntu) on Windows, configuring Docker Desktop to use WSL2, setting up SSH access to GitHub within WSL, cloning your Licentia repository, and running your Laravel application in Docker containers (via Laravel Sail). By following these steps, you’ll be able to edit code in VS Code (using Remote-WSL), run commands inside a Dockerized environment, and avoid common pitfalls when invoking Artisan or Composer directly on the host.

---

## 1. Install WSL2 (Windows Subsystem for Linux)

1. **Open PowerShell as Administrator**:

   1. Press **⊞ Win**, type **PowerShell**, right‐click **Windows PowerShell**, and choose **Run as administrator**.
   2. Run the following command to enable WSL and install Ubuntu:

      ```powershell
      wsl --install
      ```

      * This command will:

        * Enable the **WSL** feature.
        * Enable the **Virtual Machine Platform**.
        * Download and install the default Linux distro (usually Ubuntu).

   3. **Restart** your machine when prompted.

2. **Launch Ubuntu**:

   1. After reboot, press **⊞ Win**, type “Ubuntu”, and press **Enter**.
   2. On first launch, Ubuntu will finish its installation—create a **username** and **password** when prompted.
   3. You now have a `username@DESKTOP` shell running Ubuntu under WSL2.

3. **Verify WSL Version** (optional):
   In your Ubuntu terminal, run:

   ```bash
   wsl --list --verbose
   ```

   Ensure that your Ubuntu distro is listed with **VERSION 2**.

---

## 2. Install Docker Desktop and Enable WSL2 Integration

1. **Download Docker Desktop for Windows**:

   1. Go to the [Docker Desktop download page](https://www.docker.com/products/docker-desktop/) and grab the Windows installer.
   2. Run the installer and follow the prompts.
   3. **Important**: During installation, **ensure** the checkbox for using WSL2 instead of Hyper-V is selected if prompted.

2. **Configure Docker to Use WSL2**:

   1. After installation, launch **Docker Desktop** from the Start menu.
   2. Click the **gear icon** (⚙️) in the top-right to open **Settings**.
   3. Under **General**, make sure **Use the WSL 2 based engine** is checked.
   4. Go to **Resources → WSL Integration**.
   5. In the “Enable integration with additional distros” section, toggle **Ubuntu** (or whichever distro you installed) to **ON**.
   6. Click **Apply & Restart** if you make any changes.

3. **Verify Docker in WSL**:

   1. In your Ubuntu shell, run:

      ```bash
      docker version
      ```
   2. You should see both a **Client** and **Server** section, indicating Docker is reachable from within WSL2.

---

## 3. Configure WSL (Ubuntu) and Connect to GitHub via SSH

1. **Update and Upgrade Ubuntu Packages**:

   ```bash
   sudo apt update && sudo apt upgrade -y
   ```

2. **Install Git** (if not already installed):

   ```bash
   sudo apt install -y git
   ```

3. **Create a Workspace Directory** (optional but recommended):

   ```bash
   mkdir -p ~/code
   cd ~/code
   ```

4. **Generate an SSH Keypair**:

   1. Run:

      ```bash
      ssh-keygen -t ed25519 -C "your_email@example.com"
      ```

      * Press **Enter** to accept the default location (`/home/username/.ssh/id_ed25519`).
      * Optionally enter a **passphrase** (recommended for extra security) or press **Enter** for no passphrase.
   2. **Add the SSH agent** and load your key:

      ```bash
      eval "$(ssh-agent -s)"
      ssh-add ~/.ssh/id_ed25519
      ```

5. **Add Your Public Key to GitHub**:

   1. Copy the public key to your clipboard:

      ```bash
      cat ~/.ssh/id_ed25519.pub
      ```

      * Select and copy the entire contents (starting with `ssh-ed25519 ...`).
   2. In a web browser, go to **github.com → Settings → SSH and GPG keys → New SSH key**.
   3. Give it a **Title** (e.g., “WSL Ubuntu”) and **paste** the public key.
   4. Click **Add SSH key**.

6. **Test SSH Authentication**:

   ```bash
   ssh -T git@github.com
   ```

   * You should see a message:

     ```
     Hi Username! You’ve successfully authenticated, but GitHub does not provide shell access.
     ```
   * If you get any errors, double-check that you added the correct public key on GitHub.

---

## 4. Clone Your Licentia Repository

1. **In WSL (Ubuntu), Navigate to Your Workspace**:

   ```bash
   cd ~/code
   ```

2. **Clone via SSH**:

   ```bash
   git clone git@github.com:Dayne-Valourite/Licentia.git
   ```

   * This creates a `Licentia` folder under `~/code`.

3. **Enter the Project Directory**:

   ```bash
   cd Licentia
   ```

4. **Verify Remotes**:

   ```bash
   git remote -v
   ```

   * Should list `origin` as `git@github.com:Dayne-Valourite/Licentia.git` for both fetch and push.

---

## 5. Install Laravel Sail (Docker Setup) (Skip if sail is installed already)

Laravel Sail is a lightweight CLI wrapper around Docker Compose that spins up PHP, MySQL, Redis, and other services for you.

This should only be installed if sail has not been installed in the repo already, which is has been so this step can be skipped

1. **Install Composer** (if not already present in WSL):

   ```bash
   # If you haven’t installed Composer, run:
   curl -sS https://getcomposer.org/installer | php
   sudo mv composer.phar /usr/local/bin/composer

   # Verify:
   composer --version
   ```

2. **Require Laravel Sail** (inside your project):

   ```bash
   composer require laravel/sail --dev
   ```

   * You’ll see `laravel/sail` added to your `composer.json` as a dev dependency.

3. **Publish Sail’s Docker Files**:

   ```bash
   php artisan sail:install --with=mysql,redis,mailhog
   ```

   * The `--with=` flag lets you choose which services to include. Typically for Licentia you’ll want at least MySQL and Redis, but adjust as needed.
   * After running this, you’ll have:

     * A `docker` directory (e.g. `docker/8.4/Dockerfile`).
     * A `docker-compose.yml` at your project root.

4. **Review and Adjust `.env`** (if needed):

   * Make sure your database settings match Sail’s defaults:

     ```dotenv
     DB_CONNECTION=mysql
     DB_HOST=mysql
     DB_PORT=3306
     DB_DATABASE=licentia
     DB_USERNAME=sail
     DB_PASSWORD=password
     ```
   * Sail’s MySQL container exposes a database named `licentia` by default, with user `sail` and password `password`. Feel free to change them, but ensure consistency in both `.env` and `docker-compose.yml`.

---

## 6. Build and Start Your Docker Containers

1. **Ensure Docker Desktop Is Running**:

   * If Docker Desktop isn’t open, launch it now.
   * You should see the Docker icon in your system tray; hover to confirm it’s using WSL 2.

2. **Build the Sail Images** (only needed the first time or after modifying the Dockerfile):

   ```bash
   ./vendor/bin/sail build --no-cache
   ```

   * The `--no-cache` flag ensures a fresh build; omit it on subsequent builds if you want faster incremental builds.

3. **Start Sail in Detached Mode**:

   ```bash
   ./vendor/bin/sail up -d
   ```

   * This does two main things:

     1. Launches your **app** container (PHP 8.4, etc.).
     2. Spins up the named services (MySQL, Redis, MailHog).
   * After a few moments, you should see containers start in Docker Desktop’s UI or from the CLI.

4. **Confirm Containers Are Running**:

   * Inside WSL (or in PowerShell), run:

     ```bash
     docker ps
     ```

   ````
   - You should see several containers, including something like:
     - `licentia_mysql_1   mysql:8.0`
     - `licentia_redis_1   redis:alpine` (if you selected Redis)
     - `licentia_app_1     sail-8.4/app`  
   - Alternatively, use Sail’s built-in command:
     ```bash
     ./vendor/bin/sail ps
   ````

   * This will list the same running services but scoped to your project.

---

## 7. Install Dependencies & Run Migrations Inside Sail

Once your containers are up, you need to install PHP/JS dependencies and run migrations in the Docker environment.

1. **Install PHP Dependencies**:

   ```bash
   ./vendor/bin/sail composer install
   ```

   * This runs **Composer** inside the `app` container, ensuring all Laravel packages install with the correct Linux extensions.

2. **Install NPM & Build Assets**:

   ```bash
   ./vendor/bin/sail npm install
   ./vendor/bin/sail npm run dev
   ```

   * These commands install third-party JS packages and compile your front-end assets (Mix/Vite) inside the container.

3. **Generate Application Key** (if not already set):

   ```bash
   ./vendor/bin/sail artisan key:generate
   ```

4. **Run Database Migrations & Seeders**:

   ```bash
   ./vendor/bin/sail artisan migrate:fresh --seed
   ```

   * Because `DB_HOST=mysql`, the `artisan migrate` command resolves `mysql` to the MySQL container on the same Docker network.

5. **(Optional) Create a Virtual Host in `/etc/hosts`**:

   * If you prefer using a custom domain (e.g., `http://licentia.test`), edit your Windows `C:\Windows\System32\drivers\etc\hosts` and add:

     ```text
     127.0.0.1   licentia.test
     ```
   * Then modify `docker-compose.yml`’s `app` service to expose port 80 (instead of `8000`) and set a server name.
   * But by default, you can visit **`http://localhost`** (or `http://127.0.0.1:8000`) to see your app.

---

## 8. Access the Application in Your Browser

1. Open a browser and navigate to:

   ```text
   http://localhost
   ```

   * If you didn’t map to port 80, use:

     ```text
     http://localhost:8000
     ```

2. You should see Licentia’s landing page (or whatever your default route is).

3. To watch your JS changes in “hot reload” mode (if you have Vite configured), you can run:

   ```bash
   ./vendor/bin/sail npm run watch
   ```

   * Vite will watch for file changes in your container and trigger live-reload in the browser.

---

## 9. Running Artisan/Composer Commands: Why You Should Use Sail

### A. Host PHP vs. Sail’s PHP

* **Host PHP (WSL) Limitations**:

  * Your WSL-Ubuntu’s PHP CLI may not have **all** the required extensions (e.g., `pdo_mysql`, `gd`, `intl`, `opcache`) unless you explicitly install them.
  * When you run `php artisan migrate` directly in WSL, `DB_HOST=mysql` tries to resolve to a hostname “mysql” on your host network. Since outside Docker there is no such hostname, you’ll see:

    ```text
    SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for mysql failed
    ```
  * Similarly, running `composer install` natively can fail if required extensions are missing (e.g., `ext-xml`, `ext-dom`, `ext-pdo_mysql`).

* **Sail’s PHP (Inside Docker)**:

  * Laravel Sail’s container already has the required PHP extensions (as defined in the `Dockerfile`), including `pdo_mysql`, `mbstring`, `xml`, `openssl`, `gd`, etc.
  * Within the container, `DB_HOST=mysql` resolves to the MySQL service in the same Docker network.
  * Therefore, **all** calls to `artisan`, `composer`, and `npm` should be prefixed with `./vendor/bin/sail` to ensure they run in the correct environment.

### B. Example Use Cases

* **Run a Migration**:

  ```bash
  # Wrong (host PHP):
  php artisan migrate
  # → fails with "getaddrinfo for mysql failed" because host PHP can’t see the MySQL container.

  # Right (Sail PHP):
  ./vendor/bin/sail artisan migrate
  ```

* **Install a New Package**:

  ```bash
  # Wrong (host PHP):
  composer require barryvdh/laravel-debugbar
  # → might fail if host PHP is missing ext-xml or ext-dom.

  # Right (Sail PHP):
  ./vendor/bin/sail composer require barryvdh/laravel-debugbar
  ```

* **Serve the Application**:

  ```bash
  # Wrong (host PHP):
  php artisan serve --host=0.0.0.0 --port=8080
  # → will serve on host, but cannot connect to "mysql".

  # Right (Sail PHP):
  ./vendor/bin/sail up -d
  ./vendor/bin/sail artisan serve --host=0.0.0.0 --port=8080
  # → containerized PHP serves on port 8080 and can connect to MySQL.
  ```

### C. If You Really Want to Use Host PHP

1. **Install Missing Extensions**:

   ```bash
   sudo apt install -y php8.3-xml php8.3-dom php8.3-pdo-mysql php8.3-gd php8.3-intl php8.3-mbstring
   ```
2. **Run a Local MySQL** (or map Docker’s MySQL to the host):

   * Install MySQL in WSL:

     ```bash
     sudo apt install mysql-server
     sudo service mysql start
     ```
   * Change `DB_HOST` in `.env` to `127.0.0.1`.
3. **Run Commands Natively**:

   ```bash
   php artisan migrate:fresh
   ```

   * But note: mixing host PHP and container services often leads to confusion. We strongly recommend always using Sail.

---

## 10. Stopping and Cleaning Up

1. **Stop Sail and Remove Containers**:

   ```bash
   ./vendor/bin/sail down
   ```

   * This stops and removes the containers (but not your images).

2. **Prune Dangling Containers/Images** (optional):

   ```bash
   docker system prune -f
   ```

   * Removes stopped containers, unused networks, and dangling images.

3. **Restart When Needed**:

   ```bash
   ./vendor/bin/sail up -d
   ```

   * Sail will recreate containers in the same state (volumes are persistent by default).

---

## 11. Editing Code in VS Code (Remote-WSL)

1. **Install VS Code Remote-WSL Extension**:

   1. In VS Code, go to the **Extensions** view (Ctrl+Shift+X).
   2. Search for **Remote - WSL** and install it.

2. **Open Your Project in WSL**:

   1. In VS Code, press **Ctrl+Shift+P**, then type **Remote-WSL: New Window**.
   2. In the new window, use **File → Open Folder…** and navigate to:

      ```text
      \wsl$\Ubuntu\home\<your-username>\code\Licentia
      ```
   3. VS Code will reload with the status bar indicating “WSL: Ubuntu.”

3. **Use Integrated Terminal**:

   * Press **Ctrl+\`** to open a WSL terminal inside VS Code.
   * From there, you can run `./vendor/bin/sail artisan …`, `./vendor/bin/sail npm run dev`, etc., without leaving the editor.

4. **Enjoy Native Linux Tooling**:

   * Your linting, formatting, tests, and debugging all run inside WSL’s Linux environment, but you still use a Windows‐GUI editor.

---

## 12. Create a `sail` Shortcut for Easier Commands

Instead of typing `./vendor/bin/sail <command>` every time, you can define a small shell function (or alias) so that simply typing `sail <command>` will invoke Sail from the correct project directory. Follow these steps:

1. **Open your shell configuration file**  
   - For Bash (default on Ubuntu/WSL), run:  
     ```bash
     nano ~/.bashrc
     ```  
   - For Zsh, run:  
     ```bash
     nano ~/.zshrc
     ```

2. **Paste one of the following blocks at the end of the file**, depending on whether you want a project-relative function or a global lookup:

   ### Option A: Project-Relative Function  
   This version checks for `vendor/bin/sail` in the current directory and runs it. You must be in the Laravel project’s root (where `composer require laravel/sail` has already been run and the `vendor` folder exists).

   ```bash
   #
   # ── LARAVEL SAIL SHORTCUT (PROJECT-RELATIVE) ────────────────────────────────────
   #
   sail() {
     if [ -f vendor/bin/sail ]; then
       bash vendor/bin/sail "$@"
     else
       echo "Error: Could not find vendor/bin/sail in $(pwd)"
     fi
   }
   #
   # ──────────────────────────────────────────────────────────────────────────────
   #

---

## 13. Common Troubleshooting

* **If you still see “getaddrinfo for mysql failed”**:

  * Make sure you used `./vendor/bin/sail artisan …` and that `./vendor/bin/sail up -d` is running.
  * In your `.env`, ensure `DB_HOST=mysql` remains unchanged.

* **If Composer complains about missing PHP extensions**:

  * Confirm you ran `composer require laravel/sail --dev` inside Sail, or install missing `php8.3-…` extensions on the host only if you really need native CLI.

* **If Docker commands hang or error**:

  * Open Docker Desktop and verify WSL integration is ON for your Ubuntu distro.
  * Restart Docker Desktop and re-run `./vendor/bin/sail up -d`.

* **If file watchers (Vite/Mix) don’t pick up changes**:

  * Ensure your project directory is in WSL’s filesystem (`~/code/Licentia`), not on `/mnt/c/Licentia`.
  * Avoid running Docker volumes from `C:\`; always reference WSL paths.

---

## 14. Summary

By following this guide, you now have:

1. **WSL2 (Ubuntu)** installed and set as your development environment.
2. **Docker Desktop** configured to leverage WSL2.
3. An SSH keypair in WSL tied to your GitHub account for passwordless Git operations.
4. Cloned your Licentia repo directly into WSL’s native filesystem.
5. Installed Laravel Sail, built Docker images, and spun up containers for PHP, MySQL, Redis, etc.
6. Learned why you should **always** prefix commands with `./vendor/bin/sail` to avoid host/DB connectivity issues.
7. Opened the project in **Visual Studio Code** via the Remote-WSL extension for a seamless editing and terminal experience.

You’re now set up to develop Licentia, run migrations, seed data, compile assets, and push changes back to GitHub—all within a containerized, Linux-first workflow on Windows. Enjoy building!