diff --git a/main.tf b/main.tf
index ccee9726ef2e0447131c889833ee1918b94d2d40..93cfa5e8ce39b343593c9caa0bc780159966dcb7 100644
--- a/main.tf
+++ b/main.tf
@@ -26,6 +26,32 @@ resource "google_cloud_run_service" "webapp" {
 
   autogenerate_revision_name = true
 
+  metadata {
+    annotations = merge(
+      {
+        # As mentioned at https://www.terraform.io/docs/configuration/resources.html#ignore_changes
+        # placeholders need to be created as the adding the key to the map is
+        # considered a change and not ignored by ignore_changes. This needs to
+        # *always* be present in the config in order for it to appear in
+        # ignore_changes.
+        "run.googleapis.com/ingress-status" : "placeholder",
+      },
+
+      # Add the beta launch stage if required.
+      var.allowed_ingress != "all" ? {
+        # Required to be able to set ingress type.
+        "run.googleapis.com/launch-stage" : "BETA",
+      } : {},
+
+      # Specify the allowable ingress types.
+      {
+        "run.googleapis.com/ingress" : var.allowed_ingress,
+      },
+
+      var.service_annotations,
+    )
+  }
+
   template {
     metadata {
       annotations = merge(
@@ -52,7 +78,10 @@ resource "google_cloud_run_service" "webapp" {
           # Cloud SQL instances to auto-magically make appear in the container as
           # Unix sockets.
           "run.googleapis.com/cloudsql-instances" = var.sql_instance_connection_name
-        } : {}
+        } : {},
+
+        # Additional template annotations passed as a variable.
+        var.template_annotations,
       )
     }
 
@@ -108,6 +137,11 @@ resource "google_cloud_run_service" "webapp" {
       template[0].metadata[0].annotations["client.knative.dev/user-image"],
       template[0].metadata[0].annotations["run.googleapis.com/client-name"],
       template[0].metadata[0].annotations["run.googleapis.com/client-version"],
+
+      # If the allowed ingress variable is specified, ignore feedback about
+      # its status. We cannot make the presence of this ignore be dependent on
+      # "allowed_ingress" since ignore_changes needs to be a static list.
+      metadata[0].annotations["run.googleapis.com/ingress-status"],
     ]
   }
 }
diff --git a/variables.tf b/variables.tf
index 12e414956172b1b1ef3411cce4242f54ca53a0bd..73e4154a4bb834010b0a4e3fe2ca4dfa01417ba4 100644
--- a/variables.tf
+++ b/variables.tf
@@ -133,3 +133,33 @@ variable "monitoring_path" {
   default     = "/"
   description = "path component of url to be monitored"
 }
+
+variable "allowed_ingress" {
+  default     = "all"
+  description = <<EOL
+    Specify the allowed ingress to the service. Should be one of:
+    "all", "internal" or "internal-and-cloud-load-balancing".
+
+    Setting this to a value other than "all" implies that the service will be
+    moved to the "beta" launch stage. See
+    https://cloud.google.com/run/docs/troubleshooting#launch-stage-validation.
+  EOL
+}
+
+variable "service_annotations" {
+  type        = map(string)
+  default     = {}
+  description = <<EOL
+    Map containing additional annotations to be added to the Cloud Run service
+    itself.
+  EOL
+}
+
+variable "template_annotations" {
+  type        = map(string)
+  default     = {}
+  description = <<EOL
+    Map containing additional annotations to be added to the Cloud Run service
+    template.
+  EOL
+}