diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index cb5d052..8a904cc 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -2,17 +2,18 @@
 # To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
 version: 0.1
 cli:
-  version: 1.22.2
+  version: 1.22.9
 # Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins)
 plugins:
   sources:
     - id: trunk
-      ref: v1.6.1
+      ref: v1.6.6
       uri: https://github.com/trunk-io/plugins
 # Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes)
 runtimes:
   enabled:
-    - node@18.12.1
+    - go@1.21.0
+    - node@18.20.5
     - python@3.10.8
 # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration)
 lint:
@@ -21,14 +22,17 @@ lint:
       paths:
         - LICENCE.md
   enabled:
-    - actionlint@1.7.1
-    - checkov@3.2.216
+    - hadolint@2.12.1-beta
+    - shellcheck@0.10.0
+    - shfmt@3.6.0
+    - actionlint@1.7.7
+    - checkov@3.2.357
     - git-diff-check
-    - markdownlint@0.41.0
-    - prettier@3.3.3
-    - tflint@0.52.0
-    - trivy@0.54.0
-    - trufflehog@3.80.3
+    - markdownlint@0.43.0
+    - prettier@3.4.2
+    - tflint@0.55.0
+    - trivy@0.58.2
+    - trufflehog@3.88.2
     - yamllint@1.35.1
 actions:
   enabled:
diff --git a/bin/expose b/bin/expose
new file mode 100755
index 0000000..dbe18cc
Binary files /dev/null and b/bin/expose differ
diff --git a/cloud/aws/efs_file_system/security-groups.tf b/cloud/aws/efs_file_system/security-groups.tf
index 846d5f7..5179ffe 100644
--- a/cloud/aws/efs_file_system/security-groups.tf
+++ b/cloud/aws/efs_file_system/security-groups.tf
@@ -13,6 +13,7 @@ resource "aws_security_group" "efs" {
   })
 }
 resource "aws_vpc_security_group_ingress_rule" "nfs" {
+  description = "Allow NFS traffic from EFS"
   ip_protocol                  = "tcp"
   from_port                    = 2049
   to_port                      = 2049
@@ -23,6 +24,7 @@ resource "aws_vpc_security_group_ingress_rule" "nfs" {
   })
 }
 resource "aws_vpc_security_group_egress_rule" "nfs" {
+  description = "Allow NFS traffic to EFS"
   ip_protocol                  = "tcp"
   from_port                    = 2049
   to_port                      = 2049
@@ -32,7 +34,11 @@ resource "aws_vpc_security_group_egress_rule" "nfs" {
     Name = "NFS/EFS Egress"
   })
 }
+# checkov:skip=CKV_AWS_24: checkov is mis-detecting this as exposing port 22 to 0.0.0.0
+# checkov:skip=CKV_AWS_25: checkov is mis-detecting this as exposing port 3389 to 0.0.0.0
+# checkov:skip=CKV_AWS_260: checkov is mis-detecting this as exposing port 80 to 0.0.0.0
 resource "aws_vpc_security_group_ingress_rule" "ping" {
+  description = "Allow ping"
   ip_protocol                  = "icmp"
   from_port                    = 0
   to_port                      = 0
diff --git a/products/bastion/README.md b/products/bastion/README.md
index f37202e..8966b3b 100644
--- a/products/bastion/README.md
+++ b/products/bastion/README.md
@@ -1 +1 @@
-Heavy use of code pilfered from https://github.com/binlab/docker-bastion/blob/master/Dockerfile
\ No newline at end of file
+Heavy use of code pilfered from https://github.com/binlab/docker-bastion/blob/master/Dockerfile
diff --git a/products/bastion/bastion.sh b/products/bastion/bastion.sh
index 1129d5b..5a45a08 100644
--- a/products/bastion/bastion.sh
+++ b/products/bastion/bastion.sh
@@ -1,90 +1,89 @@
-#!/usr/bin/env sh
+#!/usr/bin/env bash
 
 HOST_KEYS_PATH_PREFIX="${HOST_KEYS_PATH_PREFIX:='/'}"
 HOST_KEYS_PATH="${HOST_KEYS_PATH:='/etc/ssh'}"
 
-if [ "$PUBKEY_AUTHENTICATION" == "false" ]; then
-    CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=no"
+if [[ ${PUBKEY_AUTHENTICATION} == "false" ]]; then
+	CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=no"
 else
-    CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=yes"
+	CONFIG_PUBKEY_AUTHENTICATION="-o PubkeyAuthentication=yes"
 fi
 
-if [ -n "$AUTHORIZED_KEYS" ]; then
-    CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=$AUTHORIZED_KEYS"
+if [[ -n ${AUTHORIZED_KEYS} ]]; then
+	CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=${AUTHORIZED_KEYS}"
 else
-    CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=authorized_keys"
+	CONFIG_AUTHORIZED_KEYS="-o AuthorizedKeysFile=authorized_keys"
 fi
 
-if [ -n "$TRUSTED_USER_CA_KEYS" ]; then
-    CONFIG_TRUSTED_USER_CA_KEYS="-o TrustedUserCAKeys=$TRUSTED_USER_CA_KEYS"
-    CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u"
+if [[ -n ${TRUSTED_USER_CA_KEYS} ]]; then
+	CONFIG_TRUSTED_USER_CA_KEYS="-o TrustedUserCAKeys=${TRUSTED_USER_CA_KEYS}"
+	CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u"
 else
-  CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u"
+	CONFIG_AUTHORIZED_PRINCIPALS_FILE="-o AuthorizedPrincipalsFile=/etc/ssh/auth_principals/%u"
 fi
 
-
-if [ "$GATEWAY_PORTS" == "true" ]; then
-    CONFIG_GATEWAY_PORTS="-o GatewayPorts=yes"
+if [[ ${GATEWAY_PORTS} == "true" ]]; then
+	CONFIG_GATEWAY_PORTS="-o GatewayPorts=yes"
 else
-    CONFIG_GATEWAY_PORTS="-o GatewayPorts=no"
+	CONFIG_GATEWAY_PORTS="-o GatewayPorts=no"
 fi
 
-if [ "$PERMIT_TUNNEL" == "true" ]; then
-    CONFIG_PERMIT_TUNNEL="-o PermitTunnel=yes"
+if [[ ${PERMIT_TUNNEL} == "true" ]]; then
+	CONFIG_PERMIT_TUNNEL="-o PermitTunnel=yes"
 else
-    CONFIG_PERMIT_TUNNEL="-o PermitTunnel=no"
+	CONFIG_PERMIT_TUNNEL="-o PermitTunnel=no"
 fi
 
-if [ "$X11_FORWARDING" == "true" ]; then
-    CONFIG_X11_FORWARDING="-o X11Forwarding=yes"
+if [[ ${X11_FORWARDING} == "true" ]]; then
+	CONFIG_X11_FORWARDING="-o X11Forwarding=yes"
 else
-    CONFIG_X11_FORWARDING="-o X11Forwarding=no"
+	CONFIG_X11_FORWARDING="-o X11Forwarding=no"
 fi
 
-if [ "$TCP_FORWARDING" == "false" ]; then
-    CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=no"
+if [[ ${TCP_FORWARDING} == "false" ]]; then
+	CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=no"
 else
-    CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=yes"
+	CONFIG_TCP_FORWARDING="-o AllowTcpForwarding=yes"
 fi
 
-if [ "$AGENT_FORWARDING" == "false" ]; then
-    CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=no"
+if [[ ${AGENT_FORWARDING} == "false" ]]; then
+	CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=no"
 else
-    CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=yes"
+	CONFIG_AGENT_FORWARDING="-o AllowAgentForwarding=yes"
 fi
 
-if [ ! -f "$HOST_KEYS_PATH/ssh_host_rsa_key" ]; then
-    /usr/bin/ssh-keygen -A -f "$HOST_KEYS_PATH_PREFIX"
+if [[ ! -f "${HOST_KEYS_PATH}/ssh_host_rsa_key" ]]; then
+	/usr/bin/ssh-keygen -A -f "${HOST_KEYS_PATH_PREFIX}"
 fi
 
-if [ -n "$LISTEN_ADDRESS" ]; then
-    CONFIG_LISTEN_ADDRESS="-o ListenAddress=$LISTEN_ADDRESS"
+if [[ -n ${LISTEN_ADDRESS} ]]; then
+	CONFIG_LISTEN_ADDRESS="-o ListenAddress=${LISTEN_ADDRESS}"
 else
-    CONFIG_LISTEN_ADDRESS="-o ListenAddress=0.0.0.0"
+	CONFIG_LISTEN_ADDRESS="-o ListenAddress=0.0.0.0"
 fi
 
-if [ -n "$LISTEN_PORT" ]; then
-    CONFIG_LISTEN_PORT="-o Port=$LISTEN_PORT"
+if [[ -n ${LISTEN_PORT} ]]; then
+	CONFIG_LISTEN_PORT="-o Port=${LISTEN_PORT}"
 else
-    CONFIG_LISTEN_PORT="-o Port=22"
+	CONFIG_LISTEN_PORT="-o Port=22"
 fi
 
 /usr/sbin/sshd -D -e -4 \
-    -o "HostKey=$HOST_KEYS_PATH/ssh_host_rsa_key" \
-    -o "HostKey=$HOST_KEYS_PATH/ssh_host_dsa_key" \
-    -o "HostKey=$HOST_KEYS_PATH/ssh_host_ecdsa_key" \
-    -o "HostKey=$HOST_KEYS_PATH/ssh_host_ed25519_key" \
-    -o "PasswordAuthentication=no" \
-    -o "PermitEmptyPasswords=no" \
-    -o "PermitRootLogin=no" \
-    $CONFIG_PUBKEY_AUTHENTICATION \
-    $CONFIG_AUTHORIZED_KEYS \
-    $CONFIG_GATEWAY_PORTS \
-    $CONFIG_PERMIT_TUNNEL \
-    $CONFIG_X11_FORWARDING \
-    $CONFIG_AGENT_FORWARDING \
-    $CONFIG_TCP_FORWARDING \
-    $CONFIG_TRUSTED_USER_CA_KEYS \
-    $CONFIG_AUTHORIZED_PRINCIPALS_FILE \
-    $CONFIG_LISTEN_ADDRESS \
-    $CONFIG_LISTEN_PORT
+	-o "HostKey=${HOST_KEYS_PATH}/ssh_host_rsa_key" \
+	-o "HostKey=${HOST_KEYS_PATH}/ssh_host_dsa_key" \
+	-o "HostKey=${HOST_KEYS_PATH}/ssh_host_ecdsa_key" \
+	-o "HostKey=${HOST_KEYS_PATH}/ssh_host_ed25519_key" \
+	-o "PasswordAuthentication=no" \
+	-o "PermitEmptyPasswords=no" \
+	-o "PermitRootLogin=no" \
+	"${CONFIG_PUBKEY_AUTHENTICATION}" \
+	"${CONFIG_AUTHORIZED_KEYS}" \
+	"${CONFIG_GATEWAY_PORTS}" \
+	"${CONFIG_PERMIT_TUNNEL}" \
+	"${CONFIG_X11_FORWARDING}" \
+	"${CONFIG_AGENT_FORWARDING}" \
+	"${CONFIG_TCP_FORWARDING}" \
+	"${CONFIG_TRUSTED_USER_CA_KEYS}" \
+	"${CONFIG_AUTHORIZED_PRINCIPALS_FILE}" \
+	"${CONFIG_LISTEN_ADDRESS}" \
+	"${CONFIG_LISTEN_PORT}"
diff --git a/products/bastion/docker-compose.yml b/products/bastion/docker-compose.yml
index d0ca336..8028ff0 100644
--- a/products/bastion/docker-compose.yml
+++ b/products/bastion/docker-compose.yml
@@ -33,4 +33,4 @@ services:
         target: /var/lib/bastion/authorized_keys
 
 volumes:
-  bastion:
\ No newline at end of file
+  bastion:
diff --git a/products/expose/auth.tf b/products/expose/auth.tf
new file mode 100644
index 0000000..8a80f71
--- /dev/null
+++ b/products/expose/auth.tf
@@ -0,0 +1,24 @@
+variable "username" {
+  type        = string
+  description = "The username to use for the service."
+  default     = null
+}
+variable "password" {
+  type        = string
+  description = "The password to use for the service."
+  default     = null
+}
+resource "random_pet" "username" {
+  count     = var.username == null ? 1 : 0
+  length    = 2
+  separator = ""
+}
+resource "random_string" "password" {
+  count   = var.username == null ? 1 : 0
+  length  = 32
+  special = false
+}
+locals {
+  username = var.username != null ? var.username : random_pet.username[0].id
+  password = var.password != null ? var.password : nonsensitive(random_string.password[0].result)
+}
\ No newline at end of file
diff --git a/products/expose/expose.tf b/products/expose/expose.tf
new file mode 100644
index 0000000..a45b64c
--- /dev/null
+++ b/products/expose/expose.tf
@@ -0,0 +1,26 @@
+variable "domain" {
+  type        = string
+  description = "The domain to use for the service."
+}
+module "service" {
+  source                = "../../docker/service"
+  image                 = "beyondcodegmbh/expose-server:latest"
+  service_name          = "expose"
+  stack_name            = var.stack_name
+  networks              = concat(var.networks, [module.network.network])
+  traefik               = var.traefik
+  placement_constraints = var.placement_constraints
+  mounts                = var.mounts
+  ports                 = var.ports
+  converge_enable       = false
+  environment_variables = {
+    port     = 9090
+    domain   = var.domain
+    username = local.username
+    password = local.password
+  }
+  volumes = {
+    "expose_data" = "/root/.expose"
+  }
+}
+
diff --git a/products/expose/inputs.tf b/products/expose/inputs.tf
new file mode 100644
index 0000000..bc1e85b
--- /dev/null
+++ b/products/expose/inputs.tf
@@ -0,0 +1,45 @@
+variable "stack_name" {
+  default     = "expose"
+  type        = string
+  description = "The name of the stack to create."
+}
+variable "networks" {
+  type = list(object({
+    name = string
+    id   = string
+  }))
+  default     = []
+  description = "A list of network names to attach the service to."
+}
+variable "traefik" {
+  default = null
+  type = object({
+    domain           = string
+    port             = optional(number)
+    non-ssl          = optional(bool, true)
+    ssl              = optional(bool, false)
+    rule             = optional(string)
+    middlewares      = optional(list(string))
+    network          = optional(object({ name = string, id = string }))
+    basic-auth-users = optional(list(string))
+  })
+  description = "Whether to enable traefik for the service."
+}
+variable "placement_constraints" {
+  default     = []
+  type        = list(string)
+  description = "Docker Swarm placement constraints"
+}
+variable "mounts" {
+  type        = map(string)
+  default     = {}
+  description = "A map of host paths to container paths to mount. The key is the host path, and the value is the container path."
+}
+variable "ports" {
+  type = list(object({
+    host      = optional(number, null)
+    container = number
+    protocol  = optional(string, "tcp")
+  }))
+  default = []
+}
\ No newline at end of file
diff --git a/products/expose/network.tf b/products/expose/network.tf
new file mode 100644
index 0000000..2306555
--- /dev/null
+++ b/products/expose/network.tf
@@ -0,0 +1,4 @@
+module "network" {
+  source     = "../../docker/network"
+  stack_name = var.stack_name
+}
\ No newline at end of file
diff --git a/products/expose/outputs.tf b/products/expose/outputs.tf
new file mode 100644
index 0000000..db6f510
--- /dev/null
+++ b/products/expose/outputs.tf
@@ -0,0 +1,15 @@
+output "docker_service" {
+  value = module.service.docker_service
+}
+output "network" {
+  value = module.network.network
+}
+output "endpoint" {
+  value = module.service.endpoint
+}
+output "auth" {
+  value = {
+    username = local.username
+    password = local.password
+  }
+}
\ No newline at end of file
diff --git a/products/expose/terraform.tf b/products/expose/terraform.tf
new file mode 100644
index 0000000..ff5e3bd
--- /dev/null
+++ b/products/expose/terraform.tf
@@ -0,0 +1,16 @@
+terraform {
+  required_version = "~> 1.6"
+
+  required_providers {
+    docker = {
+      source  = "kreuzwerker/docker"
+      version = "~> 3.0"
+    }
+    random = {
+      source  = "hashicorp/random"
+      version = "~> 3.5"
+    }
+  }
+}
+
+
diff --git a/products/memcached/memcached.tf b/products/memcached/memcached.tf
index aee7352..38b5b1a 100644
--- a/products/memcached/memcached.tf
+++ b/products/memcached/memcached.tf
@@ -4,7 +4,7 @@ module "service" {
   stack_name   = var.stack_name
   service_name = var.service_name
   networks     = var.networks
-  command      = ["memcached", "--memory-limit", var.memory_limit_mb, "--threads", var.threads, "--connection-limit", var.connection_limit]
+  command      = ["memcached", "-m", var.memory_limit_mb, "-t", var.threads, "-c", var.connection_limit]
   #healthcheck              = ["CMD-SHELL", "echo \"version\" | nc -vn -w 1 127.0.0.1 11211"]
   #healthcheck_start_period = "10s"
   #healthcheck_interval     = "10s"
@@ -21,8 +21,5 @@ locals {
   volumes = var.data_persist_path == null ? {
     "data" = "/var/lib/mysql"
   } : {}
-  mounts = var.data_persist_path != null ? {
-    "${var.data_persist_path}" = "/var/lib/mysql"
-  } : {}
-
+  mounts = var.data_persist_path != null ? zipmap([var.data_persist_path], ["/var/lib/mysql"]) : {}
 }
\ No newline at end of file
diff --git a/products/mysql/mysql.tf b/products/mysql/mysql.tf
index 489f14d..51d1c4b 100644
--- a/products/mysql/mysql.tf
+++ b/products/mysql/mysql.tf
@@ -24,8 +24,5 @@ locals {
   volumes = var.data_persist_path == null ? {
     "data" = "/var/lib/mysql"
   } : {}
-  mounts = var.data_persist_path != null ? {
-    "${var.data_persist_path}" = "/var/lib/mysql"
-  } : {}
-
+  mounts = var.data_persist_path != null ? zipmap([var.data_persist_path], ["/var/lib/mysql"]) : {}
 }
\ No newline at end of file
diff --git a/products/openhaystack/inputs.tf b/products/openhaystack/inputs.tf
index 50bc777..4691669 100644
--- a/products/openhaystack/inputs.tf
+++ b/products/openhaystack/inputs.tf
@@ -9,7 +9,7 @@ variable "networks" {
   }))
   default     = []
   description = "A list of network names to attach the service to."
-}
+}/*
 variable "ports" {
   type = list(object({
     host      = optional(number)
@@ -30,7 +30,7 @@ variable "ports" {
     error_message = "Protocol must be either 'tcp' or 'udp'."
     condition     = alltrue([for port in var.ports : port.protocol == "tcp" || port.protocol == "udp"])
   }
-}
+}*/
 variable "placement_constraints" {
   default     = []
   type        = list(string)
diff --git a/products/openhaystack/openhaystack.tf b/products/openhaystack/openhaystack.tf
index 90b636c..68fec1e 100644
--- a/products/openhaystack/openhaystack.tf
+++ b/products/openhaystack/openhaystack.tf
@@ -15,7 +15,6 @@ module "anisette" {
     "anisette-v3-data" = "/home/Alcoholic/.config/anisette-v3/lib/"
   }
 }
-
 module "macless-haystack" {
   source                = "../../docker/service"
   stack_name            = var.stack_name
diff --git a/products/postgres/inputs.tf b/products/postgres/inputs.tf
index 0030a3d..d490bee 100644
--- a/products/postgres/inputs.tf
+++ b/products/postgres/inputs.tf
@@ -1,3 +1,8 @@
+variable "enable" {
+  type        = bool
+  description = "Whether to enable the service."
+  default     = true
+}
 variable "postgres_image" {
   default     = "postgres"
   type        = string
diff --git a/products/postgres/postgres.tf b/products/postgres/postgres.tf
index d6a9931..4af45fa 100644
--- a/products/postgres/postgres.tf
+++ b/products/postgres/postgres.tf
@@ -1,5 +1,6 @@
 module "service" {
   source               = "../../docker/service"
+  enable               = var.enable
   image                = "${var.postgres_image}:${var.postgres_version}"
   stack_name           = var.stack_name
   service_name         = var.service_name
@@ -16,13 +17,9 @@ module "service" {
   ports                 = var.ports
   placement_constraints = var.placement_constraints
 }
-
 locals {
   volumes = var.data_persist_path == null ? {
     "data" = "/var/lib/postgres/data"
   } : {}
-  mounts = var.data_persist_path != null ? {
-    "${var.data_persist_path}" = "/var/lib/postgres/data"
-  } : {}
-
+  mounts = var.data_persist_path != null ? zipmap([var.data_persist_path], ["/var/lib/postgres/data"]) : {}
 }
\ No newline at end of file
diff --git a/products/quassel/inputs.tf b/products/quassel/inputs.tf
index 37fabad..2e17039 100644
--- a/products/quassel/inputs.tf
+++ b/products/quassel/inputs.tf
@@ -1,3 +1,8 @@
+variable "enable" {
+    type        = bool
+    description = "Whether to enable the service."
+    default     = true
+}
 variable "quassel_image" {
   default     = "lscr.io/linuxserver/quassel-core"
   type        = string
diff --git a/products/quassel/quassel.tf b/products/quassel/quassel.tf
index 8751b47..deda3a9 100644
--- a/products/quassel/quassel.tf
+++ b/products/quassel/quassel.tf
@@ -4,16 +4,17 @@ module "network" {
 }
 module "postgres" {
   source                = "../postgres"
+  enable = var.enable
   postgres_version      = "16"
   stack_name            = var.stack_name
   networks              = [module.network]
   username              = "postgres"
   database              = "postgres"
   placement_constraints = var.placement_constraints
-  ports                 = [{ container = 5432, host = 65432 }]
 }
 module "service" {
   source       = "../../docker/service"
+  enable = var.enable
   image        = "${var.quassel_image}:${var.quassel_version}"
   stack_name   = var.stack_name
   service_name = "quassel"
diff --git a/products/redis/inputs.tf b/products/redis/inputs.tf
index 246622e..07c000a 100644
--- a/products/redis/inputs.tf
+++ b/products/redis/inputs.tf
@@ -1,3 +1,8 @@
+variable "enable" {
+  type        = bool
+  description = "Whether to enable the service."
+  default     = true
+}
 variable "redis_image" {
   default     = "redis"
   type        = string
diff --git a/products/redis/redis.tf b/products/redis/redis.tf
index bdbf802..c386350 100644
--- a/products/redis/redis.tf
+++ b/products/redis/redis.tf
@@ -24,6 +24,7 @@ variable "append_only" {
 }
 module "service" {
   source       = "../../docker/service"
+  enable       = var.enable
   image        = "${var.redis_image}:${var.redis_version}"
   stack_name   = var.stack_name
   service_name = "redis"
diff --git a/products/unifi/magic-forward/magic_forward.tf b/products/unifi/magic-forward/magic_forward.tf
index df6134b..3ba4b3a 100644
--- a/products/unifi/magic-forward/magic_forward.tf
+++ b/products/unifi/magic-forward/magic_forward.tf
@@ -4,4 +4,5 @@ module "port_forward" {
   label   = var.label
   port    = var.port != null ? var.port : var.docker_service.endpoint_spec[0].ports[0].published_port
   ip      = var.target.fixed_ip
+  protocol = var.protocol
 }
\ No newline at end of file
diff --git a/products/watchtower/watchtower.tf b/products/watchtower/watchtower.tf
index 31ca443..06946c0 100644
--- a/products/watchtower/watchtower.tf
+++ b/products/watchtower/watchtower.tf
@@ -3,7 +3,7 @@ module "watchtower" {
   image                 = "containrrr/watchtower:latest"
   stack_name            = "watchtower"
   service_name          = "watchtower"
-  placement_constraints = var.placement_constraints + ["node.role == manager"]
+  placement_constraints = distinct(concat(var.placement_constraints, ["node.role == manager"]))
   command               = ["--cleanup", "--label-enable", "--interval", "3600"]
   labels = {
     "com.centurylinklabs.watchtower.enable" = "true"
diff --git a/products/yarr/inputs.tf b/products/yarr/inputs.tf
index 5e04192..2864997 100644
--- a/products/yarr/inputs.tf
+++ b/products/yarr/inputs.tf
@@ -1,3 +1,8 @@
+variable "enabled" {
+  description = "Whether to enable the services or merely provision them."
+  type        = bool
+  default     = true
+}
 variable "stack_name" {
   description = "The name of the stack"
   type        = string
@@ -16,7 +21,6 @@ variable "placement_constraints" {
   default     = []
 }
 variable "traefik" {
-  default = null
   type = object({
     domain           = string
     port             = optional(number)
@@ -29,8 +33,3 @@ variable "traefik" {
   })
   description = "Whether to enable traefik for the service."
 }
-variable "enabled" {
-  description = "Whether to enable the services or merely provision them."
-  type        = bool
-  default     = true
-}
\ No newline at end of file
diff --git a/utils/identity/locals.tf b/utils/identity/locals.tf
index 141a809..83f9082 100644
--- a/utils/identity/locals.tf
+++ b/utils/identity/locals.tf
@@ -1,5 +1,4 @@
 locals {
-  username_words = var.username_words != null ? var.username_words : floor(var.username_max_length / 3)
   username       = var.username != null ? var.username : random_pet.username[0].id
   password       = var.password != null ? nonsensitive(var.password) : nonsensitive(random_password.password[0].result)
 }
\ No newline at end of file