From 5a5fc8b240e1f836675204a8b5e917c4511f7526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=91=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=D1=80=D0=B5=D0=B2?= Date: Thu, 14 May 2026 15:51:52 +0300 Subject: [PATCH] feat: nginx landing on :80 with Kaskad support footer; sync admin footer text Co-authored-by: Cursor --- README.md | 19 ++++--- landing/Dockerfile | 3 + landing/admin-port.js | 1 + landing/index.html | 59 ++++++++++++++++++++ landing/nginx.conf | 20 +++++++ landing/styles.css | 124 ++++++++++++++++++++++++++++++++++++++++++ public/index.html | 7 +-- scripts/install.sh | 27 ++++++++- scripts/uninstall.sh | 10 +++- 9 files changed, 256 insertions(+), 14 deletions(-) create mode 100644 landing/Dockerfile create mode 100644 landing/admin-port.js create mode 100644 landing/index.html create mode 100644 landing/nginx.conf create mode 100644 landing/styles.css diff --git a/README.md b/README.md index ca52255..1cdb8df 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,11 @@ cd /opt/amnezia-admin && chmod +x scripts/install.sh && sudo SKIP_DOWNLOAD=1 bas | `ADMIN_PASSWORD` | _(генерируется)_ | Первый пароль вместо файла | | `SKIP_DOWNLOAD` | `0` | `1` — не качать GitHub, собрать из `INSTALL_DIR` | | `ALLOW_DEFAULT_PASSWORD` | `0` | `1` — см. раздел «Пароль» ниже | +| `SKIP_LANDING` | `0` | `1` — не ставить публичную страницу с футером поддержки | +| `LANDING_PORT` | `80` | Порт nginx-лендинга (если `80` занят — например `8081`) | +| `LANDING_CONTAINER` | `amnezia-web-landing` | Имя контейнера лендинга | -После установки откройте `http://IP_СЕРВЕРА:8080`. +После установки: **админ-панель** `http://IP:8080` (или ваш `HOST_PORT`), **страница с поддержкой проекта** `http://IP/` на порту лендинга (по умолчанию **80**). Кнопка на лендинге ведёт на админку с тем же `HOST_PORT`. --- @@ -111,20 +114,22 @@ ADMIN_PASSWORD=localtest node server.js ## Support links -Те же способы поддержки и контакты, что в проекте [domen_hydra](https://github.com/andrey271192/domen_hydra): +Как на главной странице установки (**лендинг на порту 80**): **Kaskad WebUI** · GitHub · Boosty · Ozon СБП · Telegram · текст поддержки. -Если проект оказался полезным — буду рад поддержке. Это помогает развивать и поддерживать его дальше. +Поддержать проект — поставь звезду на GitHub **И донат**. Связаться с автором — Telegram. | Способ | Ссылка | |--------|--------| | GitHub | [Amnezia_web](https://github.com/andrey271192/Amnezia_web) | | Boosty | [boosty.to/andrey27/donate](https://boosty.to/andrey27/donate) | -| Ozon СБП | [ссылка оплаты Ozon](https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798) | -| Telegram | [@Iot_andrey](https://t.me/Iot_andrey) — вопросы, идеи, обратная связь | +| Ozon СБП | [Ozon СБП](https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798) | +| Telegram | [@lot_andrey](https://t.me/lot_andrey) | -Файл [`.github/FUNDING.yml`](.github/FUNDING.yml) задаёт кнопку **Sponsor** на GitHub (как в [domen_hydra](https://github.com/andrey271192/domen_hydra)). +Ссылки совпадают с блоком в репозитории [domen_hydra](https://github.com/andrey271192/domen_hydra) (Boosty / Ozon), отображаются на **публичной странице** после установки и в футере админ-панели. -Тот же блок поддержки продублирован в **футере веб-интерфейса**. +Файл [`.github/FUNDING.yml`](.github/FUNDING.yml) задаёт кнопку **Sponsor** на GitHub. + +Тот же блок поддержки продублирован в **футере веб-интерфейса** и на **`http://сервер:80/`** (если лендинг не отключён). --- diff --git a/landing/Dockerfile b/landing/Dockerfile new file mode 100644 index 0000000..313f0cc --- /dev/null +++ b/landing/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:1.27-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY index.html styles.css admin-port.js /usr/share/nginx/html/ diff --git a/landing/admin-port.js b/landing/admin-port.js new file mode 100644 index 0000000..52d4a1b --- /dev/null +++ b/landing/admin-port.js @@ -0,0 +1 @@ +window.__AMNEZIA_ADMIN_PORT__ = "8080"; diff --git a/landing/index.html b/landing/index.html new file mode 100644 index 0000000..2a39a14 --- /dev/null +++ b/landing/index.html @@ -0,0 +1,59 @@ + + + + + + Сервер · AmneziaWG + + + + + + +
+

Этот сервер

+

Управление AmneziaWG

+

+ Здесь установлена админ-панель для клиентов VPN. Перейдите по ссылке ниже (порт задаётся при установке, по умолчанию 8080). +

+

+
+ + + + + + + diff --git a/landing/nginx.conf b/landing/nginx.conf new file mode 100644 index 0000000..7fdc4bd --- /dev/null +++ b/landing/nginx.conf @@ -0,0 +1,20 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + gzip on; + gzip_types text/css text/plain application/json application/javascript; + + add_header X-Content-Type-Options nosniff always; + + location / { + try_files $uri $uri/ /index.html; + } + + location ~* \.css$ { + expires 1h; + add_header Cache-Control "public, max-age=3600"; + } +} diff --git a/landing/styles.css b/landing/styles.css new file mode 100644 index 0000000..2ab7652 --- /dev/null +++ b/landing/styles.css @@ -0,0 +1,124 @@ +:root { + --bg: #070b10; + --card: #111722; + --line: rgba(255, 255, 255, 0.08); + --text: #f4f7ff; + --muted: #94a3b8; + --accent: #7dd3fc; + font-family: "DM Sans", system-ui, sans-serif; +} + +* { + box-sizing: border-box; +} + +body.page { + margin: 0; + min-height: 100vh; + display: flex; + flex-direction: column; + background: radial-gradient(circle at 20% 20%, rgba(125, 211, 252, 0.08), transparent 35%), + radial-gradient(circle at 80% 0%, rgba(94, 234, 212, 0.06), transparent 40%), + var(--bg); + color: var(--text); +} + +.landing-main { + flex: 1; + max-width: 560px; + margin: 0 auto; + padding: clamp(2rem, 6vw, 4rem) 1.25rem; +} + +.eyebrow { + letter-spacing: 0.18em; + text-transform: uppercase; + font-size: 0.72rem; + color: var(--accent); + margin: 0 0 0.5rem; +} + +.landing-main h1 { + margin: 0 0 1rem; + font-size: clamp(1.5rem, 4vw, 1.85rem); + font-weight: 700; +} + +.lead { + margin: 0 0 1.25rem; + line-height: 1.6; + color: var(--muted); +} + +.admin-row { + margin: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; +} + +.admin-btn { + display: inline-block; + padding: 0.55rem 1rem; + border-radius: 11px; + font-weight: 600; + text-decoration: none; + background: linear-gradient(135deg, #38bdf8, #22d3ee); + color: #041018; +} + +.admin-btn:hover { + filter: brightness(1.05); +} + +.muted-inline { + font-size: 0.82rem; + color: var(--muted); + word-break: break-all; +} + +.support-footer { + flex-shrink: 0; + margin-top: auto; + padding: 1.25rem clamp(1rem, 3vw, 1.5rem) 1.5rem; + border-top: 1px solid var(--line); + background: rgba(10, 15, 22, 0.92); +} + +.support-line { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.35rem 0.5rem; + font-size: 0.92rem; + color: var(--muted); +} + +.support-title { + color: var(--text); + font-weight: 700; +} + +.support-sep { + opacity: 0.55; + user-select: none; +} + +.support-line a { + color: var(--accent); + text-decoration: none; + white-space: nowrap; +} + +.support-line a:hover { + text-decoration: underline; +} + +.support-blurb { + margin: 0.65rem 0 0; + font-size: 0.82rem; + line-height: 1.45; + color: var(--muted); + max-width: 62rem; +} diff --git a/public/index.html b/public/index.html index 0b19ee2..6022cc6 100644 --- a/public/index.html +++ b/public/index.html @@ -87,7 +87,7 @@ diff --git a/scripts/install.sh b/scripts/install.sh index 6371718..8caed67 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -8,6 +8,9 @@ INSTALL_DIR="${INSTALL_DIR:-/opt/amnezia-admin}" DATA_DIR="${DATA_DIR:-/opt/amnezia-admin-data}" CONTAINER_NAME="${CONTAINER_NAME:-amnezia-admin}" HOST_PORT="${HOST_PORT:-8080}" +LANDING_CONTAINER="${LANDING_CONTAINER:-amnezia-web-landing}" +LANDING_IMAGE="${LANDING_IMAGE:-amnezia-web-landing:latest}" +LANDING_PORT="${LANDING_PORT:-80}" need_root() { if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then @@ -81,6 +84,8 @@ elif [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD: RUN_ENV+=( -e "ALLOW_DEFAULT_PASSWORD=1" ) fi +IP="$(hostname -I 2>/dev/null | awk '{print $1}' || true)" + docker run -d --name "${CONTAINER_NAME}" --restart unless-stopped \ -p "${HOST_PORT}:3980" \ -v /var/run/docker.sock:/var/run/docker.sock \ @@ -88,10 +93,28 @@ docker run -d --name "${CONTAINER_NAME}" --restart unless-stopped \ "${RUN_ENV[@]}" \ amnezia-admin:latest -IP="$(hostname -I 2>/dev/null | awk '{print $1}' || true)" +if [[ "${SKIP_LANDING:-}" != "1" ]] && [[ -d "${INSTALL_DIR}/landing" ]]; then + printf "window.__AMNEZIA_ADMIN_PORT__='%s';\n" "${HOST_PORT}" >"${INSTALL_DIR}/landing/admin-port.js" + echo "→ Сборка образа ${LANDING_IMAGE} (страница на порту ${LANDING_PORT})..." + docker build -t "${LANDING_IMAGE}" "${INSTALL_DIR}/landing" + docker rm -f "${LANDING_CONTAINER}" 2>/dev/null || true + if docker run -d --name "${LANDING_CONTAINER}" --restart unless-stopped \ + -p "${LANDING_PORT}:80" \ + "${LANDING_IMAGE}"; then + echo "→ Лендинг с блоком поддержки: http://${IP:-SERVER_IP}:${LANDING_PORT}/" + else + echo "⚠ Не удалось запустить лендинг (часто порт ${LANDING_PORT} занят). Поставьте LANDING_PORT=8081 или SKIP_LANDING=1." + fi +else + echo "→ Лендинг пропущен (SKIP_LANDING=1 или нет каталога landing)." +fi + echo "" echo "=== Готово ===" -echo "Откройте в браузере: http://${IP:-SERVER_IP}:${HOST_PORT}" +echo "Админ-панель: http://${IP:-SERVER_IP}:${HOST_PORT}" +if [[ "${SKIP_LANDING:-}" != "1" ]]; then + echo "Страница с поддержкой проекта: http://${IP:-SERVER_IP}:${LANDING_PORT}/" +fi if [[ -f "${PASS_FILE}" ]]; then echo "Первый пароль: $(cat "${PASS_FILE}")" fi diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh index 49f6224..876b8b5 100755 --- a/scripts/uninstall.sh +++ b/scripts/uninstall.sh @@ -16,9 +16,17 @@ need_root() { need_root +echo "→ Останавливаю лендинг ${LANDING_CONTAINER:-amnezia-web-landing}..." +docker rm -f "${LANDING_CONTAINER:-amnezia-web-landing}" 2>/dev/null || echo "(лендинг уже отсутствует)" + echo "→ Останавливаю контейнер ${CONTAINER_NAME}..." docker rm -f "${CONTAINER_NAME}" 2>/dev/null || echo "(контейнер уже отсутствует)" +if [[ "${REMOVE_LANDING_IMAGE:-}" == "1" ]]; then + echo "→ Удаляю образ ${LANDING_IMAGE:-amnezia-web-landing:latest}..." + docker rmi "${LANDING_IMAGE:-amnezia-web-landing:latest}" 2>/dev/null || true +fi + if [[ "${REMOVE_IMAGE:-}" == "1" ]]; then echo "→ Удаляю образ ${IMAGE_NAME}..." docker rmi "${IMAGE_NAME}" 2>/dev/null || true @@ -35,4 +43,4 @@ if [[ "${REMOVE_SRC:-}" == "1" ]]; then fi echo "Готово." -echo "Подсказка: REMOVE_DATA=1 REMOVE_SRC=1 REMOVE_IMAGE=1 curl ... | sudo bash — полная очистка." +echo "Подсказка: REMOVE_LANDING_IMAGE=1 — удалить образ лендинга; REMOVE_DATA=1 REMOVE_SRC=1 REMOVE_IMAGE=1 curl ... | sudo bash — полная очистка."