Оформление оффлайн-страницы сайта
This commit is contained in:
@@ -11,6 +11,25 @@
|
|||||||
#
|
#
|
||||||
# SSE (/api/events): отдельный handle БЕЗ encode и с flush_interval -1 — иначе сжатие/
|
# SSE (/api/events): отдельный handle БЕЗ encode и с flush_interval -1 — иначе сжатие/
|
||||||
# буферизация задержат поток событий (реал-тайм перестанет работать).
|
# буферизация задержат поток событий (реал-тайм перестанет работать).
|
||||||
|
#
|
||||||
|
# Туннель лёг (апстрим недоступен) → reverse_proxy отдаёт 502/503/504, и сниппет
|
||||||
|
# (offline) подменяет ответ на свою страницу-заглушку (/etc/caddy/maintenance/maintenance.html),
|
||||||
|
# вместо «зависшей загрузки» SPA. Файл заглушки — deploy/vps/maintenance.html.
|
||||||
|
|
||||||
|
# Заглушка «сайт недоступен» при недоступности апстрима. Импортируется в каждый сайт.
|
||||||
|
(offline) {
|
||||||
|
handle_errors {
|
||||||
|
@down expression `{http.error.status_code} in [502, 503, 504]`
|
||||||
|
handle @down {
|
||||||
|
root * /etc/caddy/maintenance
|
||||||
|
rewrite * /maintenance.html
|
||||||
|
header Cache-Control "no-store"
|
||||||
|
file_server {
|
||||||
|
status 503
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forbiddenstars.ru {
|
forbiddenstars.ru {
|
||||||
tls /etc/caddy/certs/forbiddenstars.ru/fullchain.pem /etc/caddy/certs/forbiddenstars.ru/privkey.pem
|
tls /etc/caddy/certs/forbiddenstars.ru/fullchain.pem /etc/caddy/certs/forbiddenstars.ru/privkey.pem
|
||||||
@@ -24,6 +43,7 @@ forbiddenstars.ru {
|
|||||||
encode zstd gzip
|
encode zstd gzip
|
||||||
reverse_proxy 127.0.0.1:9000
|
reverse_proxy 127.0.0.1:9000
|
||||||
}
|
}
|
||||||
|
import offline
|
||||||
}
|
}
|
||||||
|
|
||||||
forbidden-stars.ru {
|
forbidden-stars.ru {
|
||||||
@@ -38,4 +58,5 @@ forbidden-stars.ru {
|
|||||||
encode zstd gzip
|
encode zstd gzip
|
||||||
reverse_proxy 127.0.0.1:9001
|
reverse_proxy 127.0.0.1:9001
|
||||||
}
|
}
|
||||||
|
import offline
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-3
@@ -85,16 +85,26 @@ rm -rf /root/certs-tmp
|
|||||||
> как «промежуточную» часть. Если дал один файл, где leaf и chain уже вместе, — это и есть
|
> как «промежуточную» часть. Если дал один файл, где leaf и chain уже вместе, — это и есть
|
||||||
> `fullchain.pem` (склейка не нужна).
|
> `fullchain.pem` (склейка не нужна).
|
||||||
|
|
||||||
## 6. Caddyfile
|
## 6. Caddyfile + страница-заглушка
|
||||||
Скопируй `deploy/vps/Caddyfile` из репозитория в `/etc/caddy/Caddyfile`, затем:
|
Скопируй `deploy/vps/Caddyfile` из репозитория в `/etc/caddy/Caddyfile` и положи страницу
|
||||||
|
«сайт недоступен» (показывается, когда туннель к хосту лежит — вместо зависшей «Загрузки» SPA):
|
||||||
```bash
|
```bash
|
||||||
|
mkdir -p /etc/caddy/maintenance
|
||||||
|
# с локальной машины:
|
||||||
|
scp deploy/vps/maintenance.html root@186.246.51.17:/etc/caddy/maintenance/maintenance.html
|
||||||
|
# на VPS:
|
||||||
caddy validate --config /etc/caddy/Caddyfile
|
caddy validate --config /etc/caddy/Caddyfile
|
||||||
systemctl reload caddy
|
systemctl reload caddy
|
||||||
```
|
```
|
||||||
|
> Заглушка живёт в сниппете `(offline)` Caddyfile: при ответе апстрима 502/503/504
|
||||||
|
> Caddy отдаёт `/etc/caddy/maintenance/maintenance.html` со статусом 503 и `Cache-Control: no-store`.
|
||||||
|
> Правки текста/вида — в `deploy/vps/maintenance.html`, затем повтори `scp` (reload Caddy не нужен,
|
||||||
|
> файл читается на каждый запрос).
|
||||||
|
|
||||||
## 7. Проверка
|
## 7. Проверка
|
||||||
1. Подними туннель прода на Pi (см. `deploy/pi/README.md`) и/или dev/test на ПК (`run.ps1` при `LOCAL_PUBLIC=vps`).
|
1. Подними туннель прода на Pi (см. `deploy/pi/README.md`) и/или dev/test на ПК (`run.ps1` при `LOCAL_PUBLIC=vps`).
|
||||||
2. Открой `https://forbiddenstars.ru` и `https://forbidden-stars.ru`.
|
2. Открой `https://forbiddenstars.ru` и `https://forbidden-stars.ru`.
|
||||||
3. Пока соответствующий туннель не поднят — Caddy отдаёт `502`, это ожидаемо.
|
3. Пока соответствующий туннель не поднят — Caddy отдаёт страницу-заглушку «Технические шоколадки»
|
||||||
|
(HTTP 503), это ожидаемо.
|
||||||
|
|
||||||
Логи Caddy: `journalctl -u caddy -f`.
|
Логи Caddy: `journalctl -u caddy -f`.
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<!-- Сама перепроверяется: когда хост вернётся, страница перезагрузится и пустит в приложение. -->
|
||||||
|
<meta http-equiv="refresh" content="20" />
|
||||||
|
<title>Сайт недоступен — Forbidden Stars</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg: #0f1115;
|
||||||
|
--surface: #171a21;
|
||||||
|
--border: #2a2f3a;
|
||||||
|
--text: #e8eaed;
|
||||||
|
--text-muted: #9aa0aa;
|
||||||
|
--accent: #e0533d;
|
||||||
|
}
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
html, body { height: 100%; margin: 0; }
|
||||||
|
body {
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
max-width: 420px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 32px 24px;
|
||||||
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
.emoji { font-size: 56px; line-height: 1; margin-bottom: 14px; }
|
||||||
|
h1 { font-size: 22px; margin: 0 0 10px; }
|
||||||
|
p { color: var(--text-muted); font-size: 15px; line-height: 1.5; margin: 0 0 18px; }
|
||||||
|
.hint { font-size: 13px; color: var(--text-muted); }
|
||||||
|
.dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 8px; height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--accent);
|
||||||
|
margin-right: 6px;
|
||||||
|
animation: pulse 1.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="card">
|
||||||
|
<div class="emoji">🍫</div>
|
||||||
|
<h1>Технические шоколадки</h1>
|
||||||
|
<p>Сайт временно недоступен — мы уже чиним. Загляните через минутку.</p>
|
||||||
|
<div class="hint"><span class="dot"></span>Страница обновится сама, как только всё заработает</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user