diff --git a/.dockerignore b/.dockerignore
index 5c2ac98..39a8dac 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -13,7 +13,10 @@ node_modules
 .prettierignore
 .prettierrc.js
 compose-test.yaml
+compose.yaml
+compose-health-test.yaml
 Dockerfile
 README
 server-dev-only.cert
-server-dev-only.key
\ No newline at end of file
+server-dev-only.key
+ .env.healthcheck.testing
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index dc40ea4..2a071d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,4 +106,7 @@ dist
 # vscode
 .vscode
 
-compose-test.yaml
\ No newline at end of file
+compose-test.yaml
+compose.yaml
+compose-health-test.yaml
+.env.healthcheck.testing
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 53309ef..6bc24e2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,6 +9,10 @@ COPY --from=builder /app/node_modules /app/node_modules
 COPY --from=builder /app/server.js /app/server.js
 COPY --from=builder /app/src /app/src
 COPY --from=builder /app/package.json /app/package.json
+COPY --from=builder /app/healthcheck.js /app/healthcheck.js
+
+# The healthcheck can be run from here, but also from the compose file
+# HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD ["/nodejs/bin/node", "app/healthcheck.js"]
 
 CMD ["app/server.js"]
 
diff --git a/healthcheck.js b/healthcheck.js
new file mode 100644
index 0000000..c1c7d9c
--- /dev/null
+++ b/healthcheck.js
@@ -0,0 +1,114 @@
+import nodemailer from 'nodemailer'
+import axios from 'axios'
+
+const serviceURL = process.env.HEALTH_CHECK_SERVICE_URL
+const serviceName = process.env.HEALTH_CHECK_SERVICE_NAME
+const shouldPostToWebHook = process.env.HEALTH_CHECK_WEB_HOOK
+const shouldSendEmail =
+  process.env.HEALTH_CHECK_SMTP_HOST &&
+  process.env.HEALTH_CHECK_SMTP_USER &&
+  process.env.HEALTH_CHECK_SMTP_PASS &&
+  process.env.HEALTH_CHECK_EMAIL_FROM &&
+  process.env.HEALTH_CHECK_EMAIL_RECIPIENT
+
+axios
+  .get(serviceURL)
+  .then(async function (response) {
+    try {
+      const body = response.data
+      if (body.healthy === true) {
+        process.exit(0)
+      }
+      await notify(`${serviceName} is unhealthy: ${body.error}`)
+      process.exit(1)
+    } catch (error) {
+      await notify(
+        `${serviceName} is potentially unhealthy - error: ${JSON.stringify(error)}`
+      )
+      process.exit(1)
+    }
+  })
+  .catch(async (error) => {
+    await notify(
+      `${serviceName} is unhealthy and will restart after 3 tries. Error: ${error.message}`
+    )
+    process.exit(1)
+  })
+
+async function notify(message) {
+  console.log(message)
+  if (shouldSendEmail) await sendMail(message)
+  if (shouldPostToWebHook) await postToWebHook(message)
+}
+
+async function postToWebHook(text) {
+  await axios
+    .post(process.env.HEALTH_CHECK_WEB_HOOK, { text })
+    .catch((error) => {
+      console.error(error)
+    })
+}
+
+async function sendMail(message) {
+  const messageParams = {
+    from: process.env.HEALTH_CHECK_EMAIL_FROM,
+    to: process.env.HEALTH_CHECK_EMAIL_RECIPIENT,
+    subject: process.env.HEALTH_CHECK_EMAIL_SUBJECT,
+    text: message
+  }
+
+  const mailTransport = {
+    host: process.env.HEALTH_CHECK_SMTP_HOST,
+    auth: {
+      user: process.env.HEALTH_CHECK_SMTP_USER,
+      pass: process.env.HEALTH_CHECK_SMTP_PASS
+    },
+    ...(process.env.HEALTH_CHECK_SMTP_PORT && {
+      port: process.env.HEALTH_CHECK_SMTP_PORT
+    })
+  }
+
+  const transporter = nodemailer.createTransport(mailTransport)
+
+  try {
+    await transporter.sendMail(messageParams)
+  } catch (error) {
+    console.log('the email send error: ')
+    console.log(error)
+  }
+}
+
+//import * as http from 'node:http';
+/* const options = { hostname: 'SIGNER', port: (process.env.PORT || 4006), path: '/healthz', method: 'GET' };
+
+http
+    .request(options, (res) => {
+        let body = '';
+
+        res.on('data', (chunk) => {
+            body += chunk;
+        });
+
+        res.on('end', async () => {
+            try {
+                const response = JSON.parse(body);
+                if (response.healthy === true) {
+                    console.log('healthy response received: ', body);
+                    await sendMail("It worked!")
+                    process.exit(0);
+                }
+
+                console.log('Unhealthy response received: ', body);
+                await sendMail(`It worked, but with error: ${JSON.stringify(body)}`)
+                process.exit(1);
+            } catch (err) {
+                console.log('Error parsing JSON response body: ', err);
+                process.exit(1);
+            }
+        });
+    })
+    .on('error', (err) => {
+        console.log('Error: ', err);
+        process.exit(1);
+    })
+    .end(); */
diff --git a/package-lock.json b/package-lock.json
index e9a03f0..577f0b1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,7 @@
         "dotenv": "^16.0.3",
         "express": "~4.16.1",
         "morgan": "~1.9.1",
+        "nodemailer": "^6.9.13",
         "winston": "^3.10.0"
       },
       "devDependencies": {
@@ -13350,6 +13351,14 @@
         "url": "https://github.com/sponsors/antelle"
       }
     },
+    "node_modules/nodemailer": {
+      "version": "6.9.13",
+      "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz",
+      "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
     "node_modules/nodemon": {
       "version": "2.0.22",
       "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
diff --git a/package.json b/package.json
index 3e34a5f..4b3c4e3 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,8 @@
     "lint-fix": "eslint --fix .  --ext .js",
     "test": "NODE_OPTIONS=--experimental-vm-modules npx c8 mocha --timeout 10000 -r dotenv/config dotenv_config_path=src/test-fixtures/.env.testing src/*.test.js",
     "coveralls": "npm run test; c8 report --reporter=text-lcov | coveralls",
-    "prepare": "test -d node_modules/husky && husky install || echo \"husky is not installed\""
+    "prepare": "test -d node_modules/husky && husky install || echo \"husky is not installed\"",
+    "test:health": "node -r dotenv/config healthcheck.js dotenv_config_path=./.env.healthcheck.testing "
   },
   "dependencies": {
     "@digitalcredentials/bnid": "^2.1.2",
@@ -28,6 +29,7 @@
     "dotenv": "^16.0.3",
     "express": "~4.16.1",
     "morgan": "~1.9.1",
+    "nodemailer": "^6.9.13",
     "winston": "^3.10.0"
   },
   "devDependencies": {
diff --git a/src/app.js b/src/app.js
index d260214..16c1075 100644
--- a/src/app.js
+++ b/src/app.js
@@ -29,12 +29,13 @@ export async function build() {
       if (!data.proof)
         throw new SigningException(503, 'signing-service healthz failed')
     } catch (e) {
-      console.log(`exception in healthz: ${e}`)
+      console.log(`exception in healthz: ${JSON.stringify(e)}`)
       return res.status(503).json({
-        error: `signing-service healthz check failed with error: ${e}`
+        error: `signing-service healthz check failed with error: ${e}`,
+        healthy: false
       })
     }
-    res.send({ message: 'signing-service server status: ok.' })
+    res.send({ message: 'signing-service server status: ok.', healthy: true })
   })
 
   app.get('/', function (req, res) {