mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-25 21:54:16 -08:00
Merge pull request #1427 from louislam/cloudflared
Built-in ease-to-use reverse proxy with Cloudflare Tunnel
This commit is contained in:
commit
bb2b5cd6ac
|
@ -1,8 +1,11 @@
|
||||||
# DON'T UPDATE TO node:14-bullseye-slim, see #372.
|
# DON'T UPDATE TO node:14-bullseye-slim, see #372.
|
||||||
# If the image changed, the second stage image should be changed too
|
# If the image changed, the second stage image should be changed too
|
||||||
FROM node:16-buster-slim
|
FROM node:16-buster-slim
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install Curl
|
||||||
# Install Apprise, add sqlite3 cli for debugging in the future, iputils-ping for ping, util-linux for setpriv
|
# Install Apprise, add sqlite3 cli for debugging in the future, iputils-ping for ping, util-linux for setpriv
|
||||||
# Stupid python3 and python3-pip actually install a lot of useless things into Debian, specify --no-install-recommends to skip them, make the base even smaller than alpine!
|
# Stupid python3 and python3-pip actually install a lot of useless things into Debian, specify --no-install-recommends to skip them, make the base even smaller than alpine!
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
|
@ -10,3 +13,14 @@ RUN apt update && \
|
||||||
sqlite3 iputils-ping util-linux dumb-init && \
|
sqlite3 iputils-ping util-linux dumb-init && \
|
||||||
pip3 --no-cache-dir install apprise==0.9.7 && \
|
pip3 --no-cache-dir install apprise==0.9.7 && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install cloudflared
|
||||||
|
# dpkg --add-architecture arm: cloudflared do not provide armhf, this is workaround. Read more: https://github.com/cloudflare/cloudflared/issues/583
|
||||||
|
COPY extra/download-cloudflared.js ./extra/download-cloudflared.js
|
||||||
|
RUN node ./extra/download-cloudflared.js $TARGETPLATFORM && \
|
||||||
|
dpkg --add-architecture arm && \
|
||||||
|
apt update && \
|
||||||
|
apt --yes --no-install-recommends install ./cloudflared.deb && \
|
||||||
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
|
rm -f cloudflared.deb
|
||||||
|
|
||||||
|
|
44
extra/download-cloudflared.js
Normal file
44
extra/download-cloudflared.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
const http = require("https"); // or 'https' for https:// URLs
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const platform = process.argv[2];
|
||||||
|
|
||||||
|
if (!platform) {
|
||||||
|
console.error("No platform??");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let arch = null;
|
||||||
|
|
||||||
|
if (platform === "linux/amd64") {
|
||||||
|
arch = "amd64";
|
||||||
|
} else if (platform === "linux/arm64") {
|
||||||
|
arch = "arm64";
|
||||||
|
} else if (platform === "linux/arm/v7") {
|
||||||
|
arch = "arm";
|
||||||
|
} else {
|
||||||
|
console.error("Invalid platform?? " + platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = fs.createWriteStream("cloudflared.deb");
|
||||||
|
get("https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-" + arch + ".deb");
|
||||||
|
|
||||||
|
function get(url) {
|
||||||
|
http.get(url, function (res) {
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
|
console.log("Redirect to " + res.headers.location);
|
||||||
|
get(res.headers.location);
|
||||||
|
} else if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||||
|
res.pipe(file);
|
||||||
|
|
||||||
|
res.on("end", function () {
|
||||||
|
console.log("Downloaded");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(res.statusCode);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
21
package-lock.json
generated
21
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.12.1",
|
"version": "1.13.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.12.1",
|
"version": "1.13.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
"jsonwebtoken": "~8.5.1",
|
"jsonwebtoken": "~8.5.1",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"limiter": "^2.1.0",
|
"limiter": "^2.1.0",
|
||||||
|
"node-cloudflared-tunnel": "~1.0.9",
|
||||||
"nodemailer": "~6.6.5",
|
"nodemailer": "~6.6.5",
|
||||||
"notp": "~2.0.3",
|
"notp": "~2.0.3",
|
||||||
"password-hash": "~1.2.2",
|
"password-hash": "~1.2.2",
|
||||||
|
@ -11160,6 +11161,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
||||||
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A=="
|
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/node-cloudflared-tunnel": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-cloudflared-tunnel/-/node-cloudflared-tunnel-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-d0mhIM5P2ldE2yHChehC6EvnpFCkifWRzWrW81gVWdcCWqNcyISXuDdOYzRW5mwmjWuT6WNtLJoGQ84uqS4EmA==",
|
||||||
|
"dependencies": {
|
||||||
|
"command-exists": "^1.2.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
|
@ -24071,6 +24080,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
||||||
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A=="
|
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A=="
|
||||||
},
|
},
|
||||||
|
"node-cloudflared-tunnel": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-cloudflared-tunnel/-/node-cloudflared-tunnel-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-d0mhIM5P2ldE2yHChehC6EvnpFCkifWRzWrW81gVWdcCWqNcyISXuDdOYzRW5mwmjWuT6WNtLJoGQ84uqS4EmA==",
|
||||||
|
"requires": {
|
||||||
|
"command-exists": "^1.2.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
"jsonwebtoken": "~8.5.1",
|
"jsonwebtoken": "~8.5.1",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"limiter": "^2.1.0",
|
"limiter": "^2.1.0",
|
||||||
|
"node-cloudflared-tunnel": "~1.0.9",
|
||||||
"nodemailer": "~6.6.5",
|
"nodemailer": "~6.6.5",
|
||||||
"notp": "~2.0.3",
|
"notp": "~2.0.3",
|
||||||
"password-hash": "~1.2.2",
|
"password-hash": "~1.2.2",
|
||||||
|
|
|
@ -91,6 +91,7 @@ const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || args.p
|
||||||
const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined;
|
const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined;
|
||||||
const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args["ssl-cert"] || undefined;
|
const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args["ssl-cert"] || undefined;
|
||||||
const disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false;
|
const disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false;
|
||||||
|
const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CLOUDFLARED_TOKEN || undefined;
|
||||||
|
|
||||||
// 2FA / notp verification defaults
|
// 2FA / notp verification defaults
|
||||||
const twofa_verification_opts = {
|
const twofa_verification_opts = {
|
||||||
|
@ -133,6 +134,7 @@ const { statusPageSocketHandler } = require("./socket-handlers/status-page-socke
|
||||||
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
|
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
|
||||||
const TwoFA = require("./2fa");
|
const TwoFA = require("./2fa");
|
||||||
const StatusPage = require("./model/status_page");
|
const StatusPage = require("./model/status_page");
|
||||||
|
const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart } = require("./socket-handlers/cloudflared-socket-handler");
|
||||||
|
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
@ -1362,6 +1364,7 @@ exports.entryPage = "dashboard";
|
||||||
|
|
||||||
// Status Page Socket Handler for admin only
|
// Status Page Socket Handler for admin only
|
||||||
statusPageSocketHandler(socket);
|
statusPageSocketHandler(socket);
|
||||||
|
cloudflaredSocketHandler(socket);
|
||||||
databaseSocketHandler(socket);
|
databaseSocketHandler(socket);
|
||||||
|
|
||||||
debug("added all socket handlers");
|
debug("added all socket handlers");
|
||||||
|
@ -1404,6 +1407,9 @@ exports.entryPage = "dashboard";
|
||||||
|
|
||||||
initBackgroundJobs(args);
|
initBackgroundJobs(args);
|
||||||
|
|
||||||
|
// Start cloudflared at the end if configured
|
||||||
|
await cloudflaredAutoStart(cloudflaredToken);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
async function updateMonitorNotification(monitorID, notificationIDList) {
|
async function updateMonitorNotification(monitorID, notificationIDList) {
|
||||||
|
|
84
server/socket-handlers/cloudflared-socket-handler.js
Normal file
84
server/socket-handlers/cloudflared-socket-handler.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server");
|
||||||
|
const { CloudflaredTunnel } = require("node-cloudflared-tunnel");
|
||||||
|
const { io } = require("../server");
|
||||||
|
|
||||||
|
const prefix = "cloudflared_";
|
||||||
|
const cloudflared = new CloudflaredTunnel();
|
||||||
|
|
||||||
|
cloudflared.change = (running, message) => {
|
||||||
|
io.to("cloudflared").emit(prefix + "running", running);
|
||||||
|
io.to("cloudflared").emit(prefix + "message", message);
|
||||||
|
};
|
||||||
|
|
||||||
|
cloudflared.error = (errorMessage) => {
|
||||||
|
io.to("cloudflared").emit(prefix + "errorMessage", errorMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.cloudflaredSocketHandler = (socket) => {
|
||||||
|
|
||||||
|
socket.on(prefix + "join", async () => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
socket.join("cloudflared");
|
||||||
|
io.to(socket.userID).emit(prefix + "installed", cloudflared.checkInstalled());
|
||||||
|
io.to(socket.userID).emit(prefix + "running", cloudflared.running);
|
||||||
|
io.to(socket.userID).emit(prefix + "token", await setting("cloudflaredTunnelToken"));
|
||||||
|
} catch (error) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on(prefix + "leave", async () => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
socket.leave("cloudflared");
|
||||||
|
} catch (error) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on(prefix + "start", async (token) => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
if (token && typeof token === "string") {
|
||||||
|
cloudflared.token = token;
|
||||||
|
} else {
|
||||||
|
cloudflared.token = null;
|
||||||
|
}
|
||||||
|
cloudflared.start();
|
||||||
|
} catch (error) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on(prefix + "stop", async (currentPassword, callback) => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
await doubleCheckPassword(socket, currentPassword);
|
||||||
|
cloudflared.stop();
|
||||||
|
} catch (error) {
|
||||||
|
callback({
|
||||||
|
ok: false,
|
||||||
|
msg: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on(prefix + "removeToken", async () => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
await setSetting("cloudflaredTunnelToken", "");
|
||||||
|
} catch (error) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.autoStart = async (token) => {
|
||||||
|
if (!token) {
|
||||||
|
token = await setting("cloudflaredTunnelToken");
|
||||||
|
} else {
|
||||||
|
// Override the current token via args or env var
|
||||||
|
await setSetting("cloudflaredTunnelToken", token);
|
||||||
|
console.log("Use cloudflared token from args or env var");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
console.log("Start cloudflared");
|
||||||
|
cloudflared.token = token;
|
||||||
|
cloudflared.start();
|
||||||
|
}
|
||||||
|
};
|
139
src/components/settings/ReverseProxy.vue
Normal file
139
src/components/settings/ReverseProxy.vue
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h4 class="mt-4">Cloudflare Tunnel</h4>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<div>
|
||||||
|
cloudflared:
|
||||||
|
<span v-if="installed === true" class="text-primary">{{ $t("Installed") }}</span>
|
||||||
|
<span v-else-if="installed === false" class="text-danger">{{ $t("Not installed") }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{ $t("Status") }}:
|
||||||
|
<span v-if="running" class="text-primary">{{ $t("Running") }}</span>
|
||||||
|
<span v-else-if="!running" class="text-danger">{{ $t("Not running") }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="false">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="errorMessage" class="mt-3">
|
||||||
|
Message:
|
||||||
|
<textarea v-model="errorMessage" class="form-control" readonly></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p v-if="installed === false">(Download cloudflared from <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/">Cloudflare Website</a>)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- If installed show token input -->
|
||||||
|
<div v-if="installed" class="mb-2">
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="form-label" for="cloudflareTunnelToken">
|
||||||
|
Cloudflare Tunnel {{ $t("Token") }}
|
||||||
|
</label>
|
||||||
|
<HiddenInput
|
||||||
|
id="cloudflareTunnelToken"
|
||||||
|
v-model="cloudflareTunnelToken"
|
||||||
|
autocomplete="one-time-code"
|
||||||
|
:readonly="running"
|
||||||
|
/>
|
||||||
|
<div class="form-text">
|
||||||
|
<div v-if="cloudflareTunnelToken" class="mb-3">
|
||||||
|
<span v-if="!running" class="remove-token" @click="removeToken">{{ $t("Remove Token") }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Don't know how to get the token? Please read the guide:<br />
|
||||||
|
<a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy-with-Cloudflare-Tunnel" target="_blank">
|
||||||
|
https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy-with-Cloudflare-Tunnel
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button v-if="!running" class="btn btn-primary" type="submit" @click="start">
|
||||||
|
{{ $t("Start") }} cloudflared
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button v-if="running" class="btn btn-danger" type="submit" @click="$refs.confirmStop.show();">
|
||||||
|
{{ $t("Stop") }} cloudflared
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<Confirm ref="confirmStop" btn-style="btn-danger" :yes-text="$t('Stop') + ' cloudflared'" :no-text="$t('Cancel')" @yes="stop">
|
||||||
|
The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<label for="current-password2" class="form-label">
|
||||||
|
{{ $t("Current Password") }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="current-password2"
|
||||||
|
v-model="currentPassword"
|
||||||
|
type="password"
|
||||||
|
class="form-control"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Confirm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 class="mt-4">Other Software</h4>
|
||||||
|
<div>
|
||||||
|
For example: nginx, Apache and Traefik. <br />
|
||||||
|
Please read <a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy" target="_blank">https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import HiddenInput from "../../components/HiddenInput.vue";
|
||||||
|
import Confirm from "../Confirm.vue";
|
||||||
|
|
||||||
|
const prefix = "cloudflared_";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
HiddenInput,
|
||||||
|
Confirm
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
// See /src/mixins/socket.js
|
||||||
|
return this.$root.cloudflared;
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$root.getSocket().emit(prefix + "join");
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
this.$root.getSocket().emit(prefix + "leave");
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
start() {
|
||||||
|
this.$root.getSocket().emit(prefix + "start", this.cloudflareTunnelToken);
|
||||||
|
},
|
||||||
|
stop() {
|
||||||
|
this.$root.getSocket().emit(prefix + "stop", this.currentPassword, (res) => {
|
||||||
|
this.$root.toastRes(res);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeToken() {
|
||||||
|
this.$root.getSocket().emit(prefix + "removeToken");
|
||||||
|
this.cloudflareTunnelToken = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.remove-token {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -42,6 +42,14 @@ export default {
|
||||||
statusPageList: [],
|
statusPageList: [],
|
||||||
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...",
|
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...",
|
||||||
showReverseProxyGuide: true,
|
showReverseProxyGuide: true,
|
||||||
|
cloudflared: {
|
||||||
|
cloudflareTunnelToken: "",
|
||||||
|
installed: null,
|
||||||
|
running: false,
|
||||||
|
message: "",
|
||||||
|
errorMessage: "",
|
||||||
|
currentPassword: "",
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -231,6 +239,12 @@ export default {
|
||||||
this.socket.firstConnect = false;
|
this.socket.firstConnect = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// cloudflared
|
||||||
|
socket.on("cloudflared_installed", (res) => this.cloudflared.installed = res);
|
||||||
|
socket.on("cloudflared_running", (res) => this.cloudflared.running = res);
|
||||||
|
socket.on("cloudflared_message", (res) => this.cloudflared.message = res);
|
||||||
|
socket.on("cloudflared_errorMessage", (res) => this.cloudflared.errorMessage = res);
|
||||||
|
socket.on("cloudflared_token", (res) => this.cloudflared.cloudflareTunnelToken = res);
|
||||||
},
|
},
|
||||||
|
|
||||||
storage() {
|
storage() {
|
||||||
|
|
|
@ -75,6 +75,9 @@ export default {
|
||||||
notifications: {
|
notifications: {
|
||||||
title: this.$t("Notifications"),
|
title: this.$t("Notifications"),
|
||||||
},
|
},
|
||||||
|
"reverse-proxy": {
|
||||||
|
title: this.$t("Reverse Proxy"),
|
||||||
|
},
|
||||||
"monitor-history": {
|
"monitor-history": {
|
||||||
title: this.$t("Monitor History"),
|
title: this.$t("Monitor History"),
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,6 +14,7 @@ import Entry from "./pages/Entry.vue";
|
||||||
import Appearance from "./components/settings/Appearance.vue";
|
import Appearance from "./components/settings/Appearance.vue";
|
||||||
import General from "./components/settings/General.vue";
|
import General from "./components/settings/General.vue";
|
||||||
import Notifications from "./components/settings/Notifications.vue";
|
import Notifications from "./components/settings/Notifications.vue";
|
||||||
|
import ReverseProxy from "./components/settings/ReverseProxy.vue";
|
||||||
import MonitorHistory from "./components/settings/MonitorHistory.vue";
|
import MonitorHistory from "./components/settings/MonitorHistory.vue";
|
||||||
import Security from "./components/settings/Security.vue";
|
import Security from "./components/settings/Security.vue";
|
||||||
import Backup from "./components/settings/Backup.vue";
|
import Backup from "./components/settings/Backup.vue";
|
||||||
|
@ -83,6 +84,10 @@ const routes = [
|
||||||
path: "notifications",
|
path: "notifications",
|
||||||
component: Notifications,
|
component: Notifications,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "reverse-proxy",
|
||||||
|
component: ReverseProxy,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "monitor-history",
|
path: "monitor-history",
|
||||||
component: MonitorHistory,
|
component: MonitorHistory,
|
||||||
|
|
Loading…
Reference in a new issue