One way that I found to use terraform recently showed me how to create SSL certificates for my docker applications in the terraform itself. We are using two providers for this. The tls provider and the local_file provider.

Generate SSL Cert Data

To generate a private key I use the tls_private_key resource.

resource "tls_private_key" "nextcloud" {
  algorithm   = "RSA"
}

Then to generate the public key I usually use a self-signed cert from the tls_self_signed_cert resource.

resource "tls_self_signed_cert" "nextcloud" {
  key_algorithm   = "RSA"
  private_key_pem = resource.tls_private_key.nextcloud.private_key_pem

  subject {
    common_name  = "martin.com"
    organization = "Martin Household"
  }

  validity_period_hours = 99999999999

  allowed_uses = [
    "key_encipherment",
    "digital_signature",
    "server_auth",
  ]
}

This will generate all of the data we need. This provider does not create the cert files. It only creates the data itself in the resource.

Create Cert Files

To create the cert files we use the data from the two resources we last created.

# cert file creation
resource "local_file" "private_key" {
    content     = resource.tls_private_key.nextcloud.private_key_pem
    filename = "${path.cwd}/private_key.pem"
}
resource "local_file" "public_key" {
    content     = resource.tls_self_signed_cert.nextcloud.cert_pem
    filename = "${path.cwd}/public_key.pem"
}

The two files are created using the data from the tls provider.

Usage

You can use these in docker images that would require SSL. Here is example code of a container that will mount the certificates.

resource "docker_container" "nextcloud_app" {
  image = docker_image.nextcloud_ssl.latest
  name  = "nextcloud_app"
  hostname = "app"
  networks_advanced {
    name = "nextcloud_network"
  }
  ports {
    internal = 443
    external = 8443
  }
  volumes {
    volume_name = "nextcloud_app_data"
    container_path = "/var/www/html"
  }
  volumes {
    host_path = "${path.cwd}/secrets/private_key.pem"
    container_path = "/etc/ssl/private/private_key.pem"
  }
  volumes {
    host_path = "${path.cwd}/secrets/public_key.pem"
    container_path = "/etc/ssl/certs/public_key.pem"
  }
  volumes {
    host_path = "${path.cwd}/000-default.conf"
    container_path = "/etc/apache2/sites-available/000-default.conf"
  }
  env = [
      "MYSQL_PASSWORD=${var.nextcloud_db_mysql_password}",
      "MYSQL_DATABASE=nextcloud",
      "MYSQL_USER=nextcloud",
      "MYSQL_HOST=nextcloud_mariadb"
  ]
  depends_on = [
      docker_container.nextcloud_mariadb,
      docker_image.nextcloud_ssl,
      docker_network.nextcloud_network,
      tls_private_key.nextcloud,
      tls_self_signed_cert.nextcloud,
  ]
}

Notice the two certificates mounted under the volumes blocks. This can be used in many different ways for docker and other projects. A sample docker project with Nextcloud can be found here.