Visitar URL original
WordPress Deployment on the Rackspace Cloud

WordPress Deployment on the Rackspace Cloud

Quickly and easily deploying WordPress on the Rackspace Cloud on OpenStack Flex

Heat Orchestration Template (HOT) deploys a fully functional WordPress site on an Ubuntu VM in Rackspace Cloud. This template uses the practice of "infrastructure as code" and automates all the prerequisites needed for a working OpenStack environment. This means that it does the work of network stack provisioning - but it also handles server configuration, WordPress installation, and HTTPS certificate setup using Let's Encrypt.

If you're interested in learning how to use OpenStack Orchestration, see our guide here

NOTE: This does not allow you to assign an existing floating IP to the VM built by the Orchestration Stack

Features

  • Creates private network, subnet, router, and security group
  • Launches a single Ubuntu-based VM
  • Installs Apache, PHP, MySQL, and WordPress
  • Automatically installs a free HTTPS certificate via Let's Encrypt
  • Continues checking for 1.5hrs for DNS to resolve the domain correctly so that it can install the certificate
  • Opens HTTP (80) and HTTPS (443) to the world

Requirements

Before launching the stack:

Template

heat_template_version: '2018-03-02'
description: >
  HOT template to deploy a WordPress server with automatic HTTPS using Certbot,
  installed via a systemd service that retries DNS resolution post-boot.

parameters:
  private_net_cidr:
    type: string
    default: 10.0.0.0/24
  private_net_gateway:
    type: string
    default: 10.0.0.1
  image:
    type: string
    default: ubuntu-20.04
  flavor:
    type: string
    default: m1.small
  public_net:
    type: string
    description: ID of the public network
  key_name:
    type: string
    description: Name of the key pair to use for the VM instance
  site_domain:
    type: string
    description: The full domain name to be used (e.g. wpsite.example.com)
  admin_email:
    type: string
    description: Email address for Let's Encrypt registration

resources:
  private_network:
    type: OS::Neutron::Net
  private_subnet:
    type: OS::Neutron::Subnet
    properties:
      network_id: { get_resource: private_network }
      cidr: { get_param: private_net_cidr }
      gateway_ip: { get_param: private_net_gateway }
      dns_nameservers: [8.8.8.8, 8.8.4.4]
  router:
    type: OS::Neutron::Router
    properties:
      external_gateway_info:
        network: { get_param: public_net }
  router_interface:
    type: OS::Neutron::RouterInterface
    properties:
      router_id: { get_resource: router }
      subnet_id: { get_resource: private_subnet }
  vm_security_group:
    type: OS::Neutron::SecurityGroup
    properties:
      rules:
        - { protocol: tcp, port_range_min: 22, port_range_max: 22, remote_ip_prefix: 0.0.0.0/0 }
        - { protocol: tcp, port_range_min: 80, port_range_max: 80, remote_ip_prefix: 0.0.0.0/0 }
        - { protocol: tcp, port_range_min: 443, port_range_max: 443, remote_ip_prefix: 0.0.0.0/0 }
        - { protocol: icmp, remote_ip_prefix: 0.0.0.0/0 }
  vm_port:
    type: OS::Neutron::Port
    properties:
      network_id: { get_resource: private_network }
      security_groups: [ { get_resource: vm_security_group } ]
  floating_ip:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network_id: { get_param: public_net }
      port_id: { get_resource: vm_port }
  wordpress_server:
    type: OS::Nova::Server
    properties:
      name: wordpress_server
      image: { get_param: image }
      flavor: { get_param: flavor }
      key_name: { get_param: key_name }
      networks:
        - port: { get_resource: vm_port }
      user_data_format: RAW
      user_data:
        str_replace:
          params:
            __DOMAIN__: { get_param: site_domain }
            __EMAIL__: { get_param: admin_email }
          template: |
            #!/bin/bash
            apt-get update
            apt-get install -y apache2 mysql-server php php-mysql libapache2-mod-php certbot python3-certbot-apache

            mysql -e "CREATE DATABASE wordpress;"
            mysql -e "CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'password';"
            mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';"
            mysql -e "FLUSH PRIVILEGES;"

            cd /var/www/html
            wget https://wordpress.org/latest.tar.gz
            tar -xvzf latest.tar.gz
            rm latest.tar.gz
            mv wordpress/* .
            rmdir wordpress
            cp wp-config-sample.php wp-config.php
            sed -i "s/database_name_here/wordpress/" wp-config.php
            sed -i "s/username_here/wpuser/" wp-config.php
            sed -i "s/password_here/password/" wp-config.php
            chown -R www-data:www-data /var/www/html
            chmod -R 755 /var/www/html

            cat <<EOF > /usr/local/bin/wait-for-dns-certbot.sh
            #!/bin/bash
            IP=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)
            for i in {1..180}; do
              RESOLVED=$(getent ahosts __DOMAIN__ | awk '{print $1; exit}')
              if [ "$RESOLVED" == "$IP" ]; then
                certbot --apache --non-interactive --agree-tos --email __EMAIL__ -d __DOMAIN__
                systemctl reload apache2
                exit 0
              fi
              sleep 30
            done
            echo "DNS failed to resolve to correct IP after waiting."
            EOF

            chmod +x /usr/local/bin/wait-for-dns-certbot.sh
            cat <<EOF > /etc/systemd/system/certbot-wait.service
            [Unit]
            Description=Wait for DNS then run Certbot
            After=network.target
            [Service]
            ExecStart=/usr/local/bin/wait-for-dns-certbot.sh
            Type=oneshot
            RemainAfterExit=true
            [Install]
            WantedBy=multi-user.target
            EOF

            systemctl daemon-reexec
            systemctl daemon-reload
            systemctl enable certbot-wait.service
            systemctl start certbot-wait.service

            systemctl restart apache2

outputs:
  instance_ip:
    description: IP address of the WordPress server
    value: { get_attr: [ floating_ip, floating_ip_address ] }

Stack Parameters

ParameterDescriptionDefault Value
private_net_cidrCIDR block for internal network10.0.0.0/24
private_net_gatewayGateway IP for subnet10.0.0.1
imageImage to use for the VM (must be Ubuntu 20.04+)Ubuntu 24.04
flavorFlavor (hardware profile) of the VMgp.5.2.4
public_netID or name of the public networkPUBLICNET
key_nameSSH key name registered in OpenStack(required)
site_domainDomain name for the WordPress site (e.g., blog.example.com)(required)
admin_emailThe email address for the Let's Encrypt registration(required)

Note: The flavor can be changed to something more powerful if needed. See our guide on flavors here.

Accessing Your WordPress Site

Once the stack is deployed and DNS is configured:

  • Visit https://yourdomain.com/wp-admin to finish WordPress setup.
  • If HTTPS isn’t working initially, verify DNS is resolving before stack creation.

Security Notes

  • SSH (port 22), HTTP (port 80), and HTTPS (port 443) are open to the internet.
  • You may want to restrict SSH access further in a production environment.

Troubleshooting

  • DNS should be updated soon after launching the stack, Certbot will fail.
  • If your DNS is updated but the site is not accessible via https:// yet - give it at least 5-10 minutes to perform the automated checks and installations.
  • Redeploy the stack only after fixing DNS.
  • Certbot will not retry unless the server is rebooted.

Did this page help you?