Merge branch 'master' into public-dashboard

# Conflicts:
#	.dockerignore
This commit is contained in:
LouisLam 2021-09-19 15:16:13 +08:00
commit 6681f49a58
13 changed files with 180 additions and 80 deletions

View File

@ -3,8 +3,9 @@
/node_modules
/data
/out
/.do
/test
/kubernetes
/.do
**/.dockerignore
/private
**/.git

View File

@ -107,11 +107,13 @@ If you love this project, please consider giving me a ⭐.
## 🗣️ Discussion
You can also discuss or ask for help in [Issues](https://github.com/louislam/uptime-kuma/issues).
### Issues Page
You can discuss or ask for help in [Issues](https://github.com/louislam/uptime-kuma/issues).
Alternatively, you can discuss in my original post on reddit: https://www.reddit.com/r/selfhosted/comments/oi7dc7/uptime_kuma_a_fancy_selfhosted_monitoring_tool_an/
I think the real "Discussion" tab is hard to use, as it is reddit-like flow, I always missed new comments.
### Subreddit
My Reddit account: louislamlam
You can mention me if you ask question on Reddit.
https://www.reddit.com/r/UptimeKuma/
## Contribute

View File

@ -5,25 +5,26 @@ WORKDIR /app
# split the sqlite install here, so that it can caches the arm prebuilt
# do not modify it, since we don't want to re-compile the arm prebuilt again
RUN apt update && \
apt --yes install python3 python3-pip python3-dev git g++ make && \
ln -s /usr/bin/python3 /usr/bin/python && \
npm install mapbox/node-sqlite3#593c9d --build-from-source
apt --yes install python3 python3-pip python3-dev git g++ make && \
ln -s /usr/bin/python3 /usr/bin/python && \
npm install mapbox/node-sqlite3#593c9d --build-from-source
COPY . .
RUN npm install --legacy-peer-deps && npm run build && npm prune --production
RUN npm install --legacy-peer-deps && \
npm run build && \
npm prune --production && \
chmod +x /app/extra/entrypoint.sh
FROM node:14-bullseye-slim AS release
WORKDIR /app
# Install Apprise,
# add sqlite3 cli for debugging in the future
# iputils-ping for ping
# Install Apprise, add sqlite3 cli for debugging in the future, iputils-ping for ping, util-linux for setpriv
RUN apt update && \
apt --yes install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
sqlite3 \
iputils-ping && \
pip3 --no-cache-dir install apprise && \
rm -rf /var/lib/apt/lists/*
apt --yes install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
sqlite3 iputils-ping util-linux && \
pip3 --no-cache-dir install apprise && \
rm -rf /var/lib/apt/lists/*
# Copy app files from build layer
COPY --from=build /app /app
@ -31,6 +32,7 @@ COPY --from=build /app /app
EXPOSE 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
ENTRYPOINT ["extra/entrypoint.sh"]
CMD ["node", "server/server.js"]
FROM release AS nightly

View File

@ -4,22 +4,25 @@ WORKDIR /app
# split the sqlite install here, so that it can caches the arm prebuilt
RUN apk add --no-cache --virtual .build-deps make g++ python3 python3-dev git && \
ln -s /usr/bin/python3 /usr/bin/python && \
npm install mapbox/node-sqlite3#593c9d && \
apk del .build-deps && \
rm -f /usr/bin/python
ln -s /usr/bin/python3 /usr/bin/python && \
npm install mapbox/node-sqlite3#593c9d && \
apk del .build-deps && \
rm -f /usr/bin/python
COPY . .
RUN npm install --legacy-peer-deps && npm run build && npm prune --production
RUN npm install --legacy-peer-deps && \
npm run build && \
npm prune --production && \
chmod +x /app/extra/entrypoint.sh
FROM node:14-alpine3.12 AS release
WORKDIR /app
# Install apprise
RUN apk add --no-cache python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
pip3 --no-cache-dir install apprise && \
rm -rf /root/.cache
# Install apprise, iputils for non-root ping, setpriv
RUN apk add --no-cache iputils setpriv python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
pip3 --no-cache-dir install apprise && \
rm -rf /root/.cache
# Copy app files from build layer
COPY --from=build /app /app
@ -27,6 +30,7 @@ COPY --from=build /app /app
EXPOSE 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
ENTRYPOINT ["extra/entrypoint.sh"]
CMD ["node", "server/server.js"]
FROM release AS nightly

21
extra/entrypoint.sh Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env sh
# set -e Exit the script if an error happens
set -e
PUID=${PUID=1000}
PGID=${PGID=1000}
files_ownership () {
# -h Changes the ownership of an encountered symbolic link and not that of the file or directory pointed to by the symbolic link.
# -R Recursively descends the specified directories
# -c Like verbose but report only when a change is made
chown -hRc "$PUID":"$PGID" /app/data
}
echo "==> Performing startup jobs and maintenance tasks"
files_ownership
echo "==> Starting application with user $PUID group $PGID"
# --clear-groups Clear supplementary groups.
exec setpriv --reuid "$PUID" --regid "$PGID" --clear-groups "$@"

View File

@ -34,6 +34,7 @@
"test-install-script-alpine3": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/alpine3.dockerfile .",
"test-install-script-ubuntu": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu.dockerfile .",
"test-install-script-ubuntu1604": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu1604.dockerfile .",
"test-nodejs16": "docker build --progress plain -f test/ubuntu-nodejs16.dockerfile .",
"simple-dns-server": "node extra/simple-dns-server.js",
"update-language-files-with-base-lang": "cd extra/update-language-files && node index.js %npm_config_base_lang% && eslint ../../src/languages/**.js --fix",
"update-language-files": "cd extra/update-language-files && node index.js && eslint ../../src/languages/**.js --fix"

View File

@ -55,7 +55,7 @@
<div class="w-50 pe-2">
<input v-model="newDraftTag.name" class="form-control"
:class="{'is-invalid': validateDraftTag.nameInvalid}"
:placeholder="$t('name')"
:placeholder="$t('Name')"
@keydown.enter.prevent="onEnter"
/>
<div class="invalid-feedback">

View File

@ -32,7 +32,7 @@ export default {
Up: "Funcional",
Down: "Caído",
Pending: "Pendiente",
Unknown: "Desconociso",
Unknown: "Desconocido",
Pause: "Pausa",
Name: "Nombre",
Status: "Estado",

View File

@ -110,37 +110,62 @@ export default {
respTime: "Czas odp. (ms)",
notAvailableShort: "N/A",
Create: "Stwórz",
clearEventsMsg: "Jesteś pewien, że chcesz usunąć wszystkie monity dla tej strony?",
clearHeartbeatsMsg: "Are you sure want to delete all heartbeats for this monitor?",
clearEventsMsg: "Jesteś pewien, że chcesz usunąć wszystkie monitory dla tej strony?",
clearHeartbeatsMsg: "Jesteś pewien, że chcesz usunąć wszystkie bicia serca dla tego monitora?",
confirmClearStatisticsMsg: "Jesteś pewien, że chcesz usunąć WSZYSTKIE statystyki?",
"Clear Data": "Usuń dane",
Events: "Wydarzenia",
Heartbeats: "Heartbeats",
"Auto Get": "Auto Get",
Heartbeats: "Bicia serca",
"Auto Get": "Pobierz automatycznie",
enableDefaultNotificationDescription: "Dla każdego nowego monitora to powiadomienie będzie domyślnie włączone. Nadal możesz wyłączyć powiadomienia osobno dla każdego monitora.",
"Default enabled": "Domyślnie włączone",
"Also apply to existing monitors": "Również zastosuj do obecnych monitów",
Export: "Eksport",
Import: "Import",
backupDescription: "Możesz wykonać kopię zapasową wszystkich monitorów i wszystkich powiadomień w pliku JSON.",
"Also apply to existing monitors": "Również zastosuj do obecnych monitorów",
Export: "Eksportuj",
Import: "Importuj",
backupDescription: "Możesz wykonać kopię zapasową wszystkich monitorów i wszystkich powiadomień do pliku JSON.",
backupDescription2: "PS: Historia i dane zdarzeń nie są uwzględniane.",
backupDescription3: "Poufne dane, takie jak tokeny powiadomień, są zawarte w pliku eksportu, prosimy o ostrożne przechowywanie.",
alertNoFile: "Proszę wybrać plik do importu.",
alertWrongFileType: "Proszę wybrać plik JSON.",
twoFAVerifyLabel: "Proszę podaj swój token 2FA, aby sprawdzić go",
twoFAVerifyLabel: "Proszę podaj swój token 2FA, aby sprawdzić czy 2FA działa",
tokenValidSettingsMsg: "Token jest poprawny! Możesz teraz zapisać ustawienia 2FA.",
confirmEnableTwoFAMsg: "Jesteś prwien że chcesz włączyć 2FA?",
confirmDisableTwoFAMsg: "Jesteś prwien że chcesz wyłączyć 2FA?",
"Apply on all existing monitors": "Zastosuj do wszystki obecnych monitów",
"Verify Token": "Weryfikuj Token",
"Setup 2FA": "Ustaw 2FA",
confirmEnableTwoFAMsg: "Jesteś pewien że chcesz włączyć 2FA?",
confirmDisableTwoFAMsg: "Jesteś pewien że chcesz wyłączyć 2FA?",
"Apply on all existing monitors": "Zastosuj do wszystki obecnych monitorów",
"Verify Token": "Weryfikuj token",
"Setup 2FA": "Konfiguracja 2FA",
"Enable 2FA": "Włącz 2FA",
"Disable 2FA": "Wyłącz 2FA",
"2FA Settings": "Ustawienia 2FA",
"Two Factor Authentication": "Podwójna weryfikacja",
"Two Factor Authentication": "Uwierzytelnienie dwuskładnikowe",
Active: "Włączone",
Inactive: "Wyłączone",
Token: "Token",
"Show URI": "Pokaż URI",
"Clear all statistics": "Wyczyść wszystkie statystyki",
retryCheckEverySecond: "Ponawiaj co {0} sekund.",
importHandleDescription: "Wybierz 'Pomiń istniejące', jeśli chcesz pominąć każdy monitor lub powiadomienie o tej samej nazwie. 'Nadpisz' spowoduje usunięcie każdego istniejącego monitora i powiadomienia.",
confirmImportMsg: "Czy na pewno chcesz zaimportować kopię zapasową? Upewnij się, że wybrałeś właściwą opcję importu.",
"Heartbeat Retry Interval": "Częstotliwość ponawiania bicia serca",
"Import Backup": "Importuj kopię zapasową",
"Export Backup": "Eksportuj kopię zapasową",
"Skip existing": "Pomiń istniejące",
Overwrite: "Nadpisz",
Options: "Opcje",
"Keep both": "Zachowaj oba",
Tags: "Tagi",
"Add New below or Select...": "Dodaj nowy poniżej lub wybierz...",
"Tag with this name already exist.": "Tag o tej nazwie już istnieje.",
"Tag with this value already exist.": "Tag o tej wartości już istnieje.",
color: "kolor",
"value (optional)": "wartość (opcjonalnie)",
Gray: "Szary",
Red: "Czerwony",
Orange: "Pomarańczowy",
Green: "Zielony",
Blue: "Niebieski",
Indigo: "Indygo",
Purple: "Fioletowy",
Pink: "Różowy",
"Search...": "Szukaj...",
}

View File

@ -107,40 +107,65 @@ export default {
"Last Result": "Последний результат",
"Create your admin account": "Создайте аккаунт администратора",
"Repeat Password": "Повторите пароль",
respTime: "Resp. Time (ms)",
notAvailableShort: "N/A",
Create: "Create",
clearEventsMsg: "Are you sure want to delete all events for this monitor?",
clearHeartbeatsMsg: "Are you sure want to delete all heartbeats for this monitor?",
confirmClearStatisticsMsg: "Are you sure want to delete ALL statistics?",
"Clear Data": "Clear Data",
Events: "Events",
Heartbeats: "Heartbeats",
"Auto Get": "Auto Get",
enableDefaultNotificationDescription: "For every new monitor this notification will be enabled by default. You can still disable the notification separately for each monitor.",
"Default enabled": "Default enabled",
"Also apply to existing monitors": "Also apply to existing monitors",
Export: "Export",
Import: "Import",
backupDescription: "You can backup all monitors and all notifications into a JSON file.",
backupDescription2: "PS: History and event data is not included.",
backupDescription3: "Sensitive data such as notification tokens is included in the export file, please keep it carefully.",
alertNoFile: "Please select a file to import.",
alertWrongFileType: "Please select a JSON file.",
twoFAVerifyLabel: "Please type in your token to verify that 2FA is working",
tokenValidSettingsMsg: "Token is valid! You can now save the 2FA settings.",
confirmEnableTwoFAMsg: "Are you sure you want to enable 2FA?",
confirmDisableTwoFAMsg: "Are you sure you want to disable 2FA?",
"Apply on all existing monitors": "Apply on all existing monitors",
"Verify Token": "Verify Token",
"Setup 2FA": "Setup 2FA",
"Enable 2FA": "Enable 2FA",
"Disable 2FA": "Disable 2FA",
"2FA Settings": "2FA Settings",
"Two Factor Authentication": "Two Factor Authentication",
Active: "Active",
Inactive: "Inactive",
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
respTime: "Время ответа (мс)",
notAvailableShort: "Н/Д",
Create: "Создать",
clearEventsMsg: "Вы действительно хотите удалить всю статистику событий данного монитора?",
clearHeartbeatsMsg: "Вы действительно хотите удалить всю статистику опросов данного монитора?",
confirmClearStatisticsMsg: "Вы действительно хотите удалить ВСЮ статистику?",
"Clear Data": "Очистить статистику",
Events: "События",
Heartbeats: "Опросы",
"Auto Get": "Авто-получение",
enableDefaultNotificationDescription: "Для каждого нового монитора это уведомление будет включено по умолчанию. Вы всё ещё можете отключить уведомления в каждом мониторе отдельно.",
"Default enabled": "Использовать по умолчанию",
"Also apply to existing monitors": "Применить к существующим мониторам",
Export: "Экспорт",
Import: "Импорт",
backupDescription: "Вы можете сохранить резервную копию всех мониторов и уведомлений в виде JSON-файла",
backupDescription2: "P.S.: История и события сохранены не будут.",
backupDescription3: "Важные данные, такие как токены уведомлений, добавляются при экспорте, поэтому храните файлы в безопасном месте.",
alertNoFile: "Выберите файл для импорта.",
alertWrongFileType: "Выберите JSON-файл.",
twoFAVerifyLabel: "Пожалуйста, введите свой токен, чтобы проверить работу 2FA",
tokenValidSettingsMsg: "Токен действителен! Теперь вы можете сохранить настройки 2FA.",
confirmEnableTwoFAMsg: "Вы действительно хотите включить 2FA?",
confirmDisableTwoFAMsg: "Вы действительно хотите выключить 2FA?",
"Apply on all existing monitors": "Применить ко всем существующим мониторам",
"Verify Token": "Проверить токен",
"Setup 2FA": "Настройка 2FA",
"Enable 2FA": "Включить 2FA",
"Disable 2FA": "Выключить 2FA",
"2FA Settings": "Настройки 2FA",
"Two Factor Authentication": "Двухфакторная аутентификация",
Active: "Активно",
Inactive: "Неактивно",
Token: "Токен",
"Show URI": "Показать URI",
"Clear all statistics": "Очистить всю статистику",
retryCheckEverySecond: "Повторять каждые {0} секунд.",
importHandleDescription: "Выберите 'Пропустить существующие' если вы хотите пропустить каждый монитор или уведомление с таким же именем. 'Перезаписать' удалит каждый существующий монитор или уведомление.",
confirmImportMsg: "Вы действительно хотите восстановить резервную копию? Убедитесь, что вы выбрали подходящий вариант импорта.",
"Heartbeat Retry Interval": "Интервал повтора опроса",
"Import Backup": "Импорт резервной копии",
"Export Backup": "Экспорт резервной копии",
"Skip existing": "Пропустить существующие",
Overwrite: "Перезаписать",
Options: "Опции",
"Keep both": "Оставить оба",
Tags: "Теги",
"Add New below or Select...": "Добавить новое ниже или выбрать...",
"Tag with this name already exist.": "Такой тег уже существует.",
"Tag with this value already exist.": "Тег с таким значением уже существует.",
color: "цвет",
"value (optional)": "значение (опционально)",
Gray: "Серый",
Red: "Красный",
Orange: "Оранжевый",
Green: "Зелёный",
Blue: "Синий",
Indigo: "Индиго",
Purple: "Пурпурный",
Pink: "Розовый",
"Search...": "Поиск...",
}

View File

@ -50,7 +50,7 @@
<!-- TCP Port / Ping / DNS only -->
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' " class="my-3">
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
<input id="hostname" v-model="monitor.hostname" type="text" class="form-control" required>
<input id="hostname" v-model="monitor.hostname" type="text" class="form-control" :pattern="ipRegexPattern || hostnameRegexPattern" required>
</div>
<!-- For TCP Port Type -->
@ -235,6 +235,9 @@ export default {
// Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/
// eslint-disable-next-line
ipRegexPattern: "((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))",
// Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
// eslint-disable-next-line
hostnameRegexPattern: "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
}
},

View File

@ -304,6 +304,12 @@
<p>Utilizzare con attenzione.</p>
</template>
<template v-else-if="$i18n.locale === 'ru-RU' ">
<p>Вы уверены, что хотите <strong>отключить авторизацию</strong>?</p>
<p>Это подходит для <strong>тех, у кого стоит другая авторизация</strong> перед открытием Uptime Kuma, например Cloudflare Access.</p>
<p>Пожалуйста, используйте с осторожностью.</p>
</template>
<!-- English (en) -->
<template v-else>
<p>Are you sure want to <strong>disable auth</strong>?</p>

View File

@ -0,0 +1,10 @@
FROM ubuntu
WORKDIR /app
RUN apt update && apt --yes install git curl
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt --yes install nodejs
RUN git clone https://github.com/louislam/uptime-kuma.git .
RUN npm run setup
# Option 1. Try it
RUN node server/server.js