diff --git a/.dockerignore b/.dockerignore index 2386eb42..3d92084d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,8 +3,9 @@ /node_modules /data /out -/.do +/test /kubernetes +/.do **/.dockerignore /private **/.git diff --git a/README.md b/README.md index bbb9b002..ffcac83b 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/dockerfile b/dockerfile index a1000636..891b03d5 100644 --- a/dockerfile +++ b/dockerfile @@ -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 diff --git a/dockerfile-alpine b/dockerfile-alpine index a9e85c37..5e34d84a 100644 --- a/dockerfile-alpine +++ b/dockerfile-alpine @@ -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 diff --git a/extra/entrypoint.sh b/extra/entrypoint.sh new file mode 100644 index 00000000..0f1d4e2f --- /dev/null +++ b/extra/entrypoint.sh @@ -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 "$@" diff --git a/package.json b/package.json index 22fa36f9..5d7d7d42 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/src/components/TagsManager.vue b/src/components/TagsManager.vue index 82025031..7fc78a34 100644 --- a/src/components/TagsManager.vue +++ b/src/components/TagsManager.vue @@ -55,7 +55,7 @@
diff --git a/src/languages/es-ES.js b/src/languages/es-ES.js index cf6951a4..c34dbaf1 100644 --- a/src/languages/es-ES.js +++ b/src/languages/es-ES.js @@ -32,7 +32,7 @@ export default { Up: "Funcional", Down: "Caído", Pending: "Pendiente", - Unknown: "Desconociso", + Unknown: "Desconocido", Pause: "Pausa", Name: "Nombre", Status: "Estado", diff --git a/src/languages/pl.js b/src/languages/pl.js index e6936a1c..a07a7063 100644 --- a/src/languages/pl.js +++ b/src/languages/pl.js @@ -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...", } diff --git a/src/languages/ru-RU.js b/src/languages/ru-RU.js index b25b5b12..fe12982e 100644 --- a/src/languages/ru-RU.js +++ b/src/languages/ru-RU.js @@ -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...": "Поиск...", } diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 2b80880c..6d8e5820 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -50,7 +50,7 @@
- +
@@ -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])$" } }, diff --git a/src/pages/Settings.vue b/src/pages/Settings.vue index da3e7245..42542d13 100644 --- a/src/pages/Settings.vue +++ b/src/pages/Settings.vue @@ -304,6 +304,12 @@

Utilizzare con attenzione.

+ +