# Deploy the WordPress + MySQL template with OpenTofu

Source: https://docs.quake.ai/resources/deployments/deploy-wordpress-mysql-template
Markdown: https://docs.quake.ai/resources/deployments/deploy-wordpress-mysql-template.md
> Stand up WordPress with MariaDB on a private subnet and one floating IP for public HTTP access using the wordpress-mysql OpenTofu template.

---

# Deploy the WordPress + MySQL template with OpenTofu

Stand up WordPress with Nginx and PHP-FPM plus MariaDB on a private subnet using the [validated OpenTofu template](/docs/platform/validation#how-infrastructure-templates-are-checked) `wordpress-mysql`. MySQL stays on a private address; one floating IP serves the WordPress install screen over HTTP.

<PricingCompanion
  components={[
    { kind: "template", slug: "wordpress-mysql", required: true },
  ]}
/>

<Figure size="md" caption="WordPress + MySQL topology: private network, two instances, MySQL data volume, tier security groups, and one floating IP on WordPress">

```d2
direction: right

cloud: Quake AI {
  router: Router
  private: Private network {
    wp: WordPress\nNginx + PHP-FPM
    db: MariaDB\n+ data volume
  }
  fip: Floating IP\n(1)
  wp_sg: WordPress SG\nSSH + HTTP + HTTPS
  db_sg: MySQL SG\nport 3306 from subnet
}

cloud.router -> cloud.private
cloud.fip -> cloud.wp
cloud.wp_sg -> cloud.wp
cloud.db_sg -> cloud.db
cloud.wp -> cloud.db: MySQL on private IP
```

</Figure>

## Prerequisites

You need:

- A Quake AI account with [application credentials](/docs/tools/generate-app-credentials)
- OpenTofu 1.6.0 or later ([installation guide](https://opentofu.org/docs/intro/install/))
- OpenStack credentials sourced into the shell (`source openrc.sh`). See [the OpenStack CLI guide](/docs/tools/openstack-cli).
- An SSH key pair already uploaded to the project. See [Add an SSH key](/docs/tools/add-ssh-key).
- A copy of the `wordpress-mysql` template from [the template reference page](/resources/iac-templates/wordpress-mysql)
- A plan tier that supports the default flavors (`s1a.small` for WordPress and `m2a.large` for MySQL). Override both in `terraform.tfvars` if your subscription requires smaller sizes.

## Step 1: Configure variables

Copy `terraform.tfvars.example` to `terraform.tfvars` and set the required values:

```hcl
wp_domain   = "blog.example.com"
key_name    = "YOUR_KEY_NAME"
db_password = "YOUR_STRONG_PASSWORD"
```

| Variable | Purpose |
| --- | --- |
| `wp_domain` | Hostname label used to prefix network, router, and instance names |
| `key_name` | Existing SSH key pair name Nova uses at boot |
| `db_password` | Password for the WordPress database user on MariaDB |

Defaults for flavors, volume size, and network CIDR are documented on the [WordPress + MySQL on Compute](/resources/iac-templates/wordpress-mysql) reference page.

## Step 2: Apply the template

From the template directory, run:

```bash
tofu init
tofu plan
tofu apply
```

Type `yes` when prompted. Provisioning takes several minutes while cloud-init installs MariaDB and WordPress on both instances.

When the run finishes, note `wordpress_ip` and `mysql_private_ip` from the outputs.

## Step 3: Verify the WordPress install screen

Cloud-init on both instances takes several minutes after `tofu apply` completes. Poll the WordPress floating IP until HTTP returns the installation page:

```bash
curl -s -o /dev/null -w "%{http_code}\n" http://$(tofu output -raw wordpress_ip)/
```

When cloud-init finishes, the command prints `200`. Open the same URL in a browser. The page title reads **WordPress › Installation**. The MySQL tier stays on the private subnet; you reach it only through WordPress.

If the curl check returns `000` or `502`, wait two minutes and retry.

Optional: SSH to the WordPress instance while cloud-init runs:

```bash
ssh -i YOUR_PRIVATE_KEY_PATH ubuntu@$(tofu output -raw wordpress_ip)
```

## Next steps

- [WordPress + MySQL on Compute template](/resources/iac-templates/wordpress-mysql)
- [Deploy the Simple VM template](/resources/deployments/deploy-simple-vm-template)
- [Self-Managed PostgreSQL template](/resources/iac-templates/self-managed-postgres)

## Clean up

Run `tofu destroy` from the project directory when finished. Type `yes` to confirm. Verify in the Console that both instances, the data volume, and the floating IP are gone.
