diff --git a/docker/secret/config.tf b/docker/secret/config.tf
new file mode 100644
index 0000000..ff57260
--- /dev/null
+++ b/docker/secret/config.tf
@@ -0,0 +1,18 @@
+resource "random_id" "randomiser" {
+  byte_length = 2
+  keepers = {
+    stack_name = var.stack_name
+    data       = var.value
+  }
+}
+
+resource "docker_secret" "secret" {
+  name = local.secret_name
+  data = base64encode(var.value)
+
+  lifecycle {
+    create_before_destroy = true
+    ignore_changes        = [name]
+  }
+}
+
diff --git a/docker/secret/debug.tf b/docker/secret/debug.tf
new file mode 100644
index 0000000..3964912
--- /dev/null
+++ b/docker/secret/debug.tf
@@ -0,0 +1,14 @@
+resource "local_file" "secret" {
+  count           = var.debug ? 1 : 0
+  content         = var.value
+  filename        = "${local.debug_path}/${local.file_name}"
+  file_permission = "0600"
+}
+variable "debug_path" {
+  type        = string
+  description = "Path to write debug files to"
+  default     = null
+}
+locals {
+  debug_path = var.debug_path != null ? var.debug_path : "${path.root}/.debug/docker/secrets/${var.stack_name}"
+}
\ No newline at end of file
diff --git a/docker/secret/inputs.tf b/docker/secret/inputs.tf
new file mode 100644
index 0000000..0457836
--- /dev/null
+++ b/docker/secret/inputs.tf
@@ -0,0 +1,22 @@
+variable "stack_name" {
+  type        = string
+  description = "The name of the stack to deploy the service to."
+}
+variable "name" {
+  type        = string
+  description = "The name of the docker secret."
+}
+variable "value" {
+  type        = string
+  description = "The value of the docker secret."
+}
+variable "labels" {
+  type        = map(string)
+  default     = {}
+  description = "A map of labels to apply to the service"
+}
+variable "debug" {
+  type        = bool
+  default     = true
+  description = "Emit debug files in .debug directory"
+}
\ No newline at end of file
diff --git a/docker/secret/locals.tf b/docker/secret/locals.tf
new file mode 100644
index 0000000..c1ce909
--- /dev/null
+++ b/docker/secret/locals.tf
@@ -0,0 +1,24 @@
+locals {
+  path      = var.name
+  file_name = element(split("/", local.path), length(split("/", local.path)) - 1)
+  // Name can be 64 bytes long, including a null byte seemingly, limiting the length to 63.
+  // The hash is 7 bytes long. We lose 2 more bytes to the dashes. So we have 54 bytes left.
+  // I will share that into 20 bytes for the stack name, remaining bytes for the config name
+  secret_name = join("-", [
+    substr(var.stack_name, 0, 20),
+    substr(local.file_name, 0, 64 - 20 - 1 - (random_id.randomiser.byte_length * 2) - 1),
+    random_id.randomiser.hex
+  ])
+
+  // define secret labels
+  labels = merge(var.labels, {
+    "com.docker.stack.namespace" = var.stack_name
+    "ooo.grey.secret.stack"      = var.stack_name
+    #"ooo.grey.secret.created"   = plantimestamp()
+    "ooo.grey.secret.bytes" = length(var.value)
+    "ooo.grey.secret.name"  = local.secret_name
+    "ooo.grey.secret.hash"  = sha1(var.value)
+    "ooo.grey.secret.file"  = local.file_name
+    "ooo.grey.secret.path"  = local.path
+  })
+}
\ No newline at end of file
diff --git a/docker/secret/outputs.tf b/docker/secret/outputs.tf
new file mode 100644
index 0000000..e2d0206
--- /dev/null
+++ b/docker/secret/outputs.tf
@@ -0,0 +1,6 @@
+output "id" {
+  value = docker_secret.secret.id
+}
+output "name" {
+  value = docker_secret.secret.name
+}
\ No newline at end of file
diff --git a/docker/secret/terraform.tf b/docker/secret/terraform.tf
new file mode 100644
index 0000000..26d0fe2
--- /dev/null
+++ b/docker/secret/terraform.tf
@@ -0,0 +1,20 @@
+terraform {
+  required_version = "~> 1.6"
+
+  required_providers {
+    docker = {
+      source  = "kreuzwerker/docker"
+      version = "~>3.0"
+    }
+    local = {
+      source  = "hashicorp/local"
+      version = "~>2.1"
+    }
+    random = {
+      source  = "hashicorp/random"
+      version = "~>3.5"
+    }
+  }
+}
+
+
diff --git a/docker/service/inputs.tf b/docker/service/inputs.tf
index 0e1123a..a73b4a4 100644
--- a/docker/service/inputs.tf
+++ b/docker/service/inputs.tf
@@ -110,6 +110,11 @@ variable "mounts" {
   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 "secrets" {
+  type        = map(string)
+  default     = {}
+  description = "A map of secret files to create. Key being the path to the file, and the value being the content. The secret will be created using the truncated file name and a timestamp."
+}
 variable "configs" {
   type        = map(string)
   default     = {}
diff --git a/docker/service/secrets.tf b/docker/service/secrets.tf
new file mode 100644
index 0000000..e1b4496
--- /dev/null
+++ b/docker/service/secrets.tf
@@ -0,0 +1,8 @@
+module "secrets" {
+  for_each   = var.secrets
+  source     = "../../docker/secret"
+  stack_name = var.stack_name
+  name       = each.key
+  value      = each.value
+  debug_path = "${local.debug_path}/secrets"
+}
\ No newline at end of file
diff --git a/docker/service/service.tf b/docker/service/service.tf
index a3d16a3..16e2306 100644
--- a/docker/service/service.tf
+++ b/docker/service/service.tf
@@ -61,6 +61,15 @@ resource "docker_service" "instance" {
           file_name   = configs.key
         }
       }
+      # Same for secrets
+      dynamic "secrets" {
+        for_each = var.secrets
+        content {
+          secret_id   = module.secrets[secrets.key].id
+          secret_name = module.secrets[secrets.key].name
+          file_name   = secrets.key
+        }
+      }
 
       # Allow overriding DNS server in use
       dynamic "dns_config" {