diff --git a/Dockerfile b/Dockerfile
index dde01a6..31d5ef8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -58,10 +58,10 @@ COPY . .
# TODO: Reevaluate permissions (possibly reduce?)...
# Remove docs directory and ensure required directories exist
RUN rm -rf src/routes/\(docs\) \
- static/documentation \
- static/fonts/lato/full && \
- mkdir -p uploads database && \
- # TODO: Consider changing below to `chmod -R u-rwX,g=rX,o= uploads database`
+ static/documentation \
+ static/fonts/lato/full && \
+ mkdir -p uploads database && \
+ # TODO: Consider changing below to `chmod -R u-rwX,g=rX,o= uploads database`
chmod -R 750 uploads database
# Build the application and remove `devDependencies`
@@ -78,15 +78,15 @@ RUN apt-get update && apt-get install -y \
iputils-ping=3:20221126-1+deb12u1 \
sqlite3=3.40.1-2+deb12u1 \
tzdata=2024b-0+deb12u1 \
- # TODO: Is it ok to change to `curl` here so that we don't have to maintain `wget` version mismatch between Debian architectures? (`curl` is only used for the container healthcheck and because there is an Alpine variant (best!) we probably don't care if the Debian image ends up building bigger due to `curl`.)
- curl=7.88.1-10+deb12u8 && \
+ # TODO: Is it ok to change to `curl` here so that we don't have to maintain `wget` version mismatch between Debian architectures? (`curl` is only used for the container healthcheck and because there is an Alpine variant (best!) we probably don't care if the Debian image ends up building bigger due to `curl`.)
+ curl=7.88.1-10+deb12u8 && \
rm -rf /var/lib/apt/lists/*
FROM node:${ALPINE_VERSION} AS final-alpine
RUN apk add --no-cache --update \
- iputils=20240905-r0 \
- sqlite=3.48.0-r0 \
- tzdata
+ iputils=20240905-r0 \
+ sqlite=3.48.0-r0 \
+ tzdata
FROM final-${VARIANT} AS final
@@ -120,25 +120,34 @@ COPY --chown=node:node --from=builder /app/main.js ./main.js
COPY --chown=node:node --from=builder /app/openapi.json ./openapi.json
COPY --chown=node:node --from=builder /app/openapi.yaml ./openapi.yaml
+# Set capabilities for ping (before changing to non-root user)
+RUN if [ -f "/etc/alpine-release" ]; then \
+ # Alpine path
+ setcap cap_net_raw+ep /bin/ping; \
+ else \
+ # Debian path
+ setcap cap_net_raw+ep /usr/bin/ping; \
+ fi
+
# Ensure necessary directories are writable
VOLUME ["/uploads", "/database"]
# Set container timezone and make entrypoint script executable
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
chmod +x ./entrypoint.sh
- # TODO: To improve security, consider dropping unnecessary capabilities instead of granting image all network capabilities of host. (Maybe `setcap cap_net_raw+p /usr/bin/ping`, etc.) Could also drop all and then grant only the capabilities that are explicitly needed. Some examples are commented out below...
- # setcap cap_net_bind_service=+ep /usr/local/bin/node
- # setcap cap_net_bind_service=+ep /usr/bin/ping
- # setcap cap_net_bind_service=+ep /usr/bin/ping6
- # setcap cap_net_bind_service=+ep /usr/bin/tracepath
- # setcap cap_net_bind_service=+ep /usr/bin/clockdiff
+ # TODO: To improve security, consider dropping unnecessary capabilities instead of granting image all network capabilities of host. (Maybe `setcap cap_net_raw+p /usr/bin/ping`, etc.) Could also drop all and then grant only the capabilities that are explicitly needed. Some examples are commented out below...
+ # setcap cap_net_bind_service=+ep /usr/local/bin/node
+ # setcap cap_net_bind_service=+ep /usr/bin/ping
+ # setcap cap_net_bind_service=+ep /usr/bin/ping6
+ # setcap cap_net_bind_service=+ep /usr/bin/tracepath
+ # setcap cap_net_bind_service=+ep /usr/bin/clockdiff
# Expose the application port
EXPOSE $PORT
# Add a healthcheck to the container; `wget` vs. `curl` depending on base image. Using this approach because `wget` does not actually maintain versioning across architectures, so we cannot pin a `wget` version (in above `final-debian` base, `apt-get install`) between differing architectures (e.g. arm64, amd64)
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
- CMD sh -c 'if [ -f "/etc/alpine-release" ]; then wget --quiet --spider http://localhost:$HEALTHCHECK_PORT$HEALTHCHECK_PATH || exit 1; else curl --silent --head --fail http://localhost:$HEALTHCHECK_PORT$HEALTHCHECK_PATH || exit 1; fi'
+ CMD sh -c 'if [ -f "/etc/alpine-release" ]; then wget --quiet --spider http://localhost:$HEALTHCHECK_PORT$HEALTHCHECK_PATH || exit 1; else curl --silent --head --fail http://localhost:$HEALTHCHECK_PORT$HEALTHCHECK_PATH || exit 1; fi'
# TODO: Revisit letting user define $PUID & $PGID overrides (e.g. `addgroup -g $PGID newgroup && adduser -D -G newgroup -u $PUID node`) as well as potentially ensure no root user exists. (Make sure no processes are running as root, first!)
# Use a non-root user (recommended for security)
diff --git a/package.json b/package.json
index 15b2213..27f8117 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "kener",
- "version": "3.2.2",
+ "version": "3.2.3",
"private": false,
"license": "MIT",
"description": "Kener: An open-source Node.js status page application for real-time service monitoring, incident management, and customizable reporting. Simplify service outage tracking, enhance incident communication, and ensure a seamless user experience.",
diff --git a/src/lib/server/notification/webhook.js b/src/lib/server/notification/webhook.js
index c747de7..74b3ab3 100644
--- a/src/lib/server/notification/webhook.js
+++ b/src/lib/server/notification/webhook.js
@@ -13,7 +13,7 @@ class Webhook {
constructor(trigger_meta, method, siteData, monitorData) {
const kenerHeader = {
"Content-Type": "application/json",
- "User-Agent": "Kener/3.2.2",
+ "User-Agent": "Kener/3.2.3",
};
let headers = trigger_meta.headers;
this.trigger_meta = trigger_meta;
diff --git a/src/lib/server/startup.js b/src/lib/server/startup.js
index 0f53758..f7cd592 100644
--- a/src/lib/server/startup.js
+++ b/src/lib/server/startup.js
@@ -1,19 +1,32 @@
// @ts-nocheck
import figlet from "figlet";
-
import { Cron } from "croner";
-
import { Minuter } from "./cron-minute.js";
import db from "./db/db.js";
import { GetAllSiteData, GetMonitorsParsed, HashString } from "./controllers/controller.js";
import { fileURLToPath } from "url";
-import { dirname } from "path";
+import { dirname, resolve } from "path";
+import fs from "fs";
const jobs = [];
process.env.TZ = "UTC";
let isStartUP = true;
+// Get the version from package.json
+const getVersion = () => {
+ try {
+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = dirname(__filename);
+ const packagePath = resolve(__dirname, "../../../package.json");
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
+ return packageJson.version;
+ } catch (error) {
+ console.error("Error reading version:", error);
+ return "unknown";
+ }
+};
+
const scheduleCronJobs = async () => {
// Fetch and map all active monitors, creating a unique hash for each
const activeMonitors = (await GetMonitorsParsed({ status: "ACTIVE" })).map((monitor) => ({
@@ -72,12 +85,15 @@ async function Startup() {
mainJob.trigger();
- figlet("Kener is UP!", function (err, data) {
+ const version = getVersion();
+
+ figlet("Kener v" + version, function (err, data) {
if (err) {
console.log("Something went wrong...");
return;
}
console.log(data);
+ console.log(`Kener version ${version} is running!`);
});
}
diff --git a/src/routes/(docs)/+layout.svelte b/src/routes/(docs)/+layout.svelte
index 37e55f2..68eaaf3 100644
--- a/src/routes/(docs)/+layout.svelte
+++ b/src/routes/(docs)/+layout.svelte
@@ -110,7 +110,7 @@
Kener Documentation
- 3.2.2
+ 3.2.3
@@ -202,7 +202,7 @@