diff --git a/docker-pgbackweb/inputs.tf b/docker-pgbackweb/inputs.tf
new file mode 100644
index 0000000..505a3c3
--- /dev/null
+++ b/docker-pgbackweb/inputs.tf
@@ -0,0 +1,25 @@
+variable "pgbackweb_image" {
+  default = "eduardolat/pgbackweb"
+}
+variable "pgbackweb_version" {
+  default = "latest"
+}
+variable "stack_name" {
+  default     = "backup"
+  type        = string
+  description = "The name of the stack to create."
+}
+variable "service_name" {
+  default     = "pgbackweb"
+  type        = string
+  description = "The name of the service to create."
+}
+variable "placement_constraints" {
+  default     = []
+  type        = list(string)
+  description = "Docker Swarm placement constraints"
+}
+variable "networks" {
+  type    = list(string)
+  default = []
+}
\ No newline at end of file
diff --git a/docker-pgbackweb/nginx.tf b/docker-pgbackweb/nginx.tf
new file mode 100644
index 0000000..fe0ae14
--- /dev/null
+++ b/docker-pgbackweb/nginx.tf
@@ -0,0 +1,28 @@
+variable "nginx_hostname" {
+  type    = string
+  default = null
+}
+variable "acme_certificate" {
+  type = object({
+    private_key_pem = string
+    certificate_pem = string
+    issuer_pem      = string
+  })
+  default = null
+}
+
+module "nginx_config" {
+  count         = var.nginx_hostname != null ? 1 : 0
+  source        = "../nginx/nginx-site-available"
+  service_name  = module.pgbackweb.service_name
+  hostname      = var.nginx_hostname
+  upstream_host = "${module.pgbackweb.service_name}:8085"
+  config_prefix = "nginx"
+  certificate   = var.acme_certificate
+}
+output "nginx_files" {
+  value = var.nginx_hostname != null ? module.nginx_config[0].files : []
+}
+output "endpoint" {
+  value = var.nginx_hostname
+}
\ No newline at end of file
diff --git a/docker-pgbackweb/pgbackweb.tf b/docker-pgbackweb/pgbackweb.tf
new file mode 100644
index 0000000..f03cccc
--- /dev/null
+++ b/docker-pgbackweb/pgbackweb.tf
@@ -0,0 +1,38 @@
+module "network" {
+  source     = "../docker-network"
+  stack_name = var.stack_name
+}
+resource "random_password" "encryption_key" {
+  length  = 32
+  special = false
+}
+module "pgbackweb" {
+  source = "../docker-service"
+  image  = "eduardolat/pgbackweb"
+  environment_variables = {
+    PBW_ENCRYPTION_KEY       = nonsensitive(random_password.encryption_key.result)
+    PBW_POSTGRES_CONN_STRING = "postgres://${module.postgres.username}:${module.postgres.password}@${module.postgres.service_name}:5432?sslmode=disable"
+  }
+  stack_name            = var.stack_name
+  service_name          = var.service_name
+  networks              = concat([module.network.network], var.networks)
+  placement_constraints = var.placement_constraints
+}
+module "postgres" {
+  source                = "../docker-postgres"
+  postgres_version      = "16"
+  stack_name            = var.stack_name
+  networks              = [module.network.network]
+  placement_constraints = var.placement_constraints
+  database              = "pgbackweb"
+  username              = "pgbackweb"
+  ports = {
+    64000 = 5432
+  }
+}
+output "pgbackweb" {
+  value = module.pgbackweb
+}
+output "database" {
+  value = module.postgres
+}
\ No newline at end of file
diff --git a/docker-pgbackweb/terraform.tf b/docker-pgbackweb/terraform.tf
new file mode 100644
index 0000000..0703661
--- /dev/null
+++ b/docker-pgbackweb/terraform.tf
@@ -0,0 +1,14 @@
+terraform {
+  required_providers {
+    docker = {
+      source  = "kreuzwerker/docker"
+      version = "~>3.0"
+    }
+    random = {
+      source  = "hashicorp/random"
+      version = "~> 3.5"
+    }
+  }
+}
+
+
diff --git a/docker-redis/credentials.tf b/docker-redis/credentials.tf
new file mode 100644
index 0000000..ea962db
--- /dev/null
+++ b/docker-redis/credentials.tf
@@ -0,0 +1,8 @@
+resource "random_password" "auth" {
+  length  = 16
+  special = false
+}
+
+locals {
+  auth = var.auth != null ? var.auth : nonsensitive(random_password.auth.result)
+}
\ No newline at end of file
diff --git a/docker-redis/inputs.tf b/docker-redis/inputs.tf
new file mode 100644
index 0000000..16331ce
--- /dev/null
+++ b/docker-redis/inputs.tf
@@ -0,0 +1,35 @@
+variable "redis_image" {
+  default     = "ghcr.io/benzine-framework/redis"
+  type        = string
+  description = "The docker image to use for the redis service."
+}
+variable "redis_version" {
+  default     = "7"
+  type        = string
+  description = "The version of the docker image to use for the redis service."
+}
+
+variable "auth" {
+  default     = null
+  type        = string
+  description = "The password for the database. If none is provided, a random password will be generated."
+}
+
+# Pass-thru variables
+variable "stack_name" {
+  type = string
+}
+variable "networks" {
+  type    = list(string)
+  default = []
+}
+variable "ports" {
+  type        = map(number)
+  default     = {}
+  description = "A map of port mappings to expose on the host. The key is the host port, and the value is the container port."
+}
+variable "placement_constraints" {
+  default     = []
+  type        = list(string)
+  description = "Docker Swarm placement constraints"
+}
\ No newline at end of file
diff --git a/docker-redis/outputs.tf b/docker-redis/outputs.tf
new file mode 100644
index 0000000..35c2fc0
--- /dev/null
+++ b/docker-redis/outputs.tf
@@ -0,0 +1,9 @@
+output "auth" {
+  value = local.auth
+}
+output "service_name" {
+  value = module.service.service_name
+}
+output "ports" {
+  value = module.service.ports
+}
\ No newline at end of file
diff --git a/docker-redis/postgres.tf b/docker-redis/postgres.tf
new file mode 100644
index 0000000..ee280ef
--- /dev/null
+++ b/docker-redis/postgres.tf
@@ -0,0 +1,13 @@
+module "service" {
+  source       = "../docker-service"
+  image        = "${var.redis_image}:${var.redis_version}"
+  command      = ["redis-server", "--requirepass", local.auth, "--appendonly", "yes", "--save", 60, 1, "--loglevel", "warning"]
+  stack_name   = var.stack_name
+  service_name = "redis"
+  networks     = var.networks
+  volumes = {
+    "data" = "/data",
+  }
+  ports                 = var.ports
+  placement_constraints = var.placement_constraints
+}
\ No newline at end of file
diff --git a/docker-redis/terraform.tf b/docker-redis/terraform.tf
new file mode 100644
index 0000000..0703661
--- /dev/null
+++ b/docker-redis/terraform.tf
@@ -0,0 +1,14 @@
+terraform {
+  required_providers {
+    docker = {
+      source  = "kreuzwerker/docker"
+      version = "~>3.0"
+    }
+    random = {
+      source  = "hashicorp/random"
+      version = "~> 3.5"
+    }
+  }
+}
+
+
diff --git a/docker-service/inputs.tf b/docker-service/inputs.tf
index 606ec4b..2aa19a9 100644
--- a/docker-service/inputs.tf
+++ b/docker-service/inputs.tf
@@ -5,6 +5,11 @@ variable "command" {
   type    = list(string)
   default = null
 }
+variable "one_shot" {
+  type        = bool
+  default     = false
+  description = "Whether to run the service as a one-shot task."
+}
 variable "stack_name" {
   type = string
 }
diff --git a/docker-service/service.tf b/docker-service/service.tf
index 112d756..28bded1 100644
--- a/docker-service/service.tf
+++ b/docker-service/service.tf
@@ -54,8 +54,10 @@ resource "docker_service" "instance" {
         name = networks_advanced.value
       }
     }
+
+    # Apply restart policy
     restart_policy {
-      condition    = "any"
+      condition    = var.one_shot ? "none" : "any"
       delay        = "0s"
       window       = "0s"
       max_attempts = 0
diff --git a/docker-statping/nginx.tf b/docker-statping/nginx.tf
index 3616eb3..85f1bd3 100644
--- a/docker-statping/nginx.tf
+++ b/docker-statping/nginx.tf
@@ -10,7 +10,6 @@ variable "acme_certificate" {
   })
   default = null
 }
-
 module "nginx_config" {
   count         = var.nginx_hostname != null ? 1 : 0
   source        = "../nginx/nginx-site-available"
@@ -19,4 +18,7 @@ module "nginx_config" {
   upstream_host = "${module.service.service_name}:8080"
   config_prefix = "nginx"
   certificate   = var.acme_certificate
+}
+output "nginx_files" {
+  value = var.nginx_hostname != null ? module.nginx_config[0].files : []
 }
\ No newline at end of file
diff --git a/docker-statping/outputs.tf b/docker-statping/outputs.tf
index 6a776f6..15a2e8f 100644
--- a/docker-statping/outputs.tf
+++ b/docker-statping/outputs.tf
@@ -11,6 +11,3 @@ output "statping" {
     }
   }
 }
-output "nginx_files" {
-  value = var.nginx_hostname != null ? module.nginx_config[0].files : []
-}
\ No newline at end of file