Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions configuration/cloudflare-tunnel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Cloudflare Tunnel

Warden integrates with [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) to expose local development environments to the public internet. This is useful for:

- Sharing work-in-progress with clients or teammates
- Testing webhooks from external services
- Mobile device testing on real domains
- QA review without deploying to staging

## Prerequisites

- A [Cloudflare account](https://dash.cloudflare.com/sign-up)
- A domain configured in Cloudflare (DNS managed by Cloudflare)

## Setup

### 1. Authenticate with Cloudflare

```{code-block} bash
warden cf login
```

This opens your browser for Cloudflare authentication. A `cert.pem` file is saved to `~/.warden/etc/cloudflared/`.

### 2. Create a tunnel

```{code-block} bash
warden cf create
```

This creates a tunnel named `warden` (or pass a custom name: `warden cf create mytunnel`). The tunnel ID is saved to `~/.warden/.env` as `WARDEN_CLOUDFLARED_TUNNEL_ID`.

### 3. Start global services

```{code-block} bash
warden svc up
```

The `cloudflared` container starts automatically when `WARDEN_CLOUDFLARED_TUNNEL_ID` is set.

### 4. Configure a project

Add `TRAEFIK_PUBLIC_DOMAIN` to your project's `.env`:

```{code-block} bash
TRAEFIK_PUBLIC_DOMAIN=myproject.example.com
```

### 5. Configure DNS in Cloudflare

In the [Cloudflare dashboard](https://dash.cloudflare.com/), add a CNAME record pointing your domain to the tunnel:

| Type | Name | Target |
|------|------|--------|
| CNAME | myproject | `<tunnel-id>.cfargotunnel.com` |
| CNAME | *.myproject | `<tunnel-id>.cfargotunnel.com` |

Replace `<tunnel-id>` with your tunnel ID from `warden cf status`.

### 6. Start the project

```{code-block} bash
warden env up
```

Warden automatically regenerates the cloudflared config to include your project's domain. Your site is now accessible at `https://myproject.example.com`.

## How It Works

```
Internet → Cloudflare Edge → cloudflared container → Traefik → nginx → php-fpm
```

1. **cloudflared** maintains a persistent connection to Cloudflare's edge network
2. Incoming requests for your domain are forwarded through the tunnel to the local **cloudflared** container
3. **cloudflared** routes the request to **Traefik** (the local reverse proxy)
4. **Traefik** matches the `Host` header to the correct project and forwards to **nginx**
5. **nginx** serves the request from **php-fpm** as usual

The cloudflared configuration is automatically regenerated whenever you run `warden env up`, `warden env down`, `warden env start`, or `warden env stop`.

## Configuration

### Global (`~/.warden/.env`)

| Variable | Description |
|----------|-------------|
| `WARDEN_CLOUDFLARED_TUNNEL_ID` | Tunnel UUID. Set automatically by `warden cf create`. When present, enables the cloudflared service. |

### Project (`.env`)

| Variable | Description |
|----------|-------------|
| `TRAEFIK_PUBLIC_DOMAIN` | Public domain for this project (e.g., `myproject.example.com`). When set, the project is exposed via the Cloudflare Tunnel. |

## CLI Reference

| Command | Description |
|---------|-------------|
| `warden cf login` | Authenticate with Cloudflare (opens browser) |
| `warden cf create [name]` | Create a new tunnel (default name: `warden`) |
| `warden cf delete` | Delete the tunnel from Cloudflare |
| `warden cf status` | Show tunnel status and connected domains |
| `warden cf update` | Force-regenerate cloudflared config and restart |
| `warden cf logout` | Remove all cloudflared credentials and config |

## Troubleshooting

### Tunnel not connecting

1. Check the cloudflared container is running: `warden svc ps`
2. Check logs: `warden svc logs cloudflared`
3. Verify credentials exist: `ls ~/.warden/etc/cloudflared/`

### Domain not routing

1. Check the domain label is set: `docker inspect <nginx-container> | grep cf.domain`
2. Verify the config was generated: `cat ~/.warden/etc/cloudflared/config.yml`
3. Force regenerate: `warden cf update`
4. Check DNS records in Cloudflare dashboard point to `<tunnel-id>.cfargotunnel.com`

### Certificate errors

The cloudflared-to-Traefik connection uses `noTLSVerify: true` because Traefik uses Warden's self-signed certificates. This is expected and only affects the local tunnel segment — the public-facing connection uses Cloudflare's edge certificates.
43 changes: 43 additions & 0 deletions environments/customizing.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,49 @@ services:
```
There you can specify a custom Nginx configuration which will be included following the `.conf` files within the `/etc/nginx/available.d` directory: `include /etc/nginx/default.d/*.conf`

## Custom Commands

Warden supports adding custom commands at both the project and global level. Each custom command consists of two files:

* `<name>.cmd` — the bash script that runs when you execute `warden <name>`
* `<name>.help` — the help text displayed in `warden help` output (required for the command to appear in the help listing)

### Command locations

* **Project-level:** `<project>/.warden/commands/` — available only within that project
* **Global:** `~/.warden/commands/` — available in all projects

When a command name exists in multiple locations, the resolution order is: project → global → built-in. This means project commands can override global ones, and both can override built-in commands.

### Example

Create a project command that clears all Magento caches:

`.warden/commands/flush.cmd`:
```bash
#!/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 exec -T php-fpm bin/magento cache:flush
```

`.warden/commands/flush.help`:
```bash
#!/usr/bin/env bash
WARDEN_USAGE=$(cat <<EOF
\033[33mUsage:\033[0m
flush

\033[33mDescription:\033[0m
Flush all Magento caches
EOF
)
```

Then run it with `warden flush`.

For a real-world example, see the [Magento 2 environment template](https://github.com/wardenenv/warden-env-magento2/tree/develop/.warden/commands).

## Magento 1 Specific Customizations

If you use a `modman` structure, initialize the environment in your project path.
Expand Down
1 change: 1 addition & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Under the hood `docker-compose` is used to control everything which Warden runs
* 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.
* Cloudflare Tunnel integration for exposing local environments to the public internet.
* 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.

Expand Down
2 changes: 2 additions & 0 deletions services.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ After running `warden svc up` for the first time following installation, the fol
* [https://portainer.warden.test/](https://portainer.warden.test/)
* [https://dnsmasq.warden.test/](https://dnsmasq.warden.test/)
* [https://mailhog.warden.test/](https://mailhog.warden.test/)
* Cloudflare Tunnel (`warden cf status` — when configured)

## Customizable Settings

Expand All @@ -16,6 +17,7 @@ The following options are available (with default values indicated):
* `TRAEFIK_LISTEN=127.0.0.1` may be set to `0.0.0.0` for example to have Traefik accept connections from other devices on the local network.
* `WARDEN_RESTART_POLICY=always` may be set to `no` to prevent Docker from restarting these service containers or any other valid [restart policy](https://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy) value.
* `WARDEN_SERVICE_DOMAIN=warden.test` may be set to a domain of your choosing if so desired. Please note that this will not currently change network settings or alter `dnsmasq` configuration. Any TLD other than `test` will require DNS resolution be manually configured.
* `WARDEN_CLOUDFLARED_TUNNEL_ID` is set automatically by `warden cf create` and enables the Cloudflare Tunnel service. See {doc}`configuration/cloudflare-tunnel` for setup instructions.

:::{warning}
Setting ``TRAEFIK_LISTEN=0.0.0.0`` can be quite useful in some cases, but be aware that causing Traefik to listen for requests publicly poses a security risk when on public WiFi or networks otherwise outside of your control.
Expand Down
Loading