← блог
Практичний VPS-сетап для статичного портфоліо

Практичний VPS-сетап для статичного портфоліо

Невеликий продакшн-сетап: статичні файли Astro за nginx, HTTPS і заголовки безпеки, правила кешу, PM2 та один необов’язковий API-сервіс.

автор Данило— переглядів

Самостійний хостинг статичного портфоліо не кращий за керовану платформу автоматично. Він міняє зручність на контроль і перетворює невеликий сайт на місце для практики з DNS, TLS, nginx, кешем та обслуговуванням сервера. Це цінно, коли навчання є частиною мети, і зайве, коли треба лише швидко опублікувати сторінку.

Нижче — навмисно малий приклад. Домен, порти та застосунок вигадані, а конфігураційні підходи спираються на першоджерела за посиланнями.

Невеликий продакшн-шлях

Припустімо, portfolio.example — Astro-сайт з необов’язковим лічильником переглядів. Звичайним сторінкам не потрібен Node-процес:

браузер ──> nginx ──> dist/
              └────> /api/views ──> Node на 127.0.0.1:4602

nginx віддає згенеровані HTML, CSS, JavaScript, шрифти й зображення напряму. Лише /api/views доходить до локального сервісу. Якщо лічильник зупинився, статті однаково мають відкриватися: декоративна метрика не може стати причиною падіння сторінки.

Preview-процес Astro може окремо працювати на 127.0.0.1:4321, але не входить у продакшн-запит. Розділення preview і production не дає звичайному restart перетворитися на публічний інцидент.

Одна збірка — звичайні файли

Деплой може складатися з двох команд:

npm ci
npm run build

Збірка записує статичний результат у dist/, а nginx використовує цю директорію як root. Контентне оновлення не потребує restart application server. Це головна перевага надійності: для відкриття статті не потрібні база даних, серверний рендер або Node-процес.

Атомарний деплой безпечніший за пофайловий запис у live-директорію. Продакшн-варіант може збирати кожну версію окремо, перевіряти її й лише потім перемикати symlink. Попередня директорія залишається для швидкого відкату.

Один канонічний хост і HTTPS

Звичайний HTTP перенаправляється на HTTPS, а канонічним обирається або apex, або www. Другий HTTPS-хост теж має вести на перший. Так не виникає кілька публічних версій одного URL, а canonical, cookies та аналітика залишаються передбачуваними.

Let’s Encrypt використовує ACME для перевірки контролю над доменом і рекомендує Certbot як стартовий клієнт. Автоподовження треба перевірити насправді: активний timer не доводить, що наступний challenge завершиться успішно.

HTTP/2 поверх TLS — розумна база. HTTP/3 варто додавати, коли його підтримує встановлена збірка nginx і вимірювання виправдовує зміну. Новий протокол не замінює правильний кеш чи швидку відповідь.

Кеш за стабільністю URL

Практичний поділ виглядає так:

Один строк для всього сайту легше написати, але важче підтримувати. Рік безпечний лише тоді, коли новий вміст створює новий URL. Браузерні рішення детальніше описані в статті про те, як зберегти швидкість Astro-сайту.

Заголовки безпеки — політика, а не значок

Продакшн-відповіді зазвичай потрібні HSTS, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, Permissions-Policy і заборони на вбудовування. Гайд OWASP із перевірки заголовків наголошує: присутності недостатньо. Дубльовані, суперечливі або надто широкі значення послаблюють політику.

CSP може починатися з default-src 'self' і відкривати лише потрібні джерела. Нову політику краще спершу запустити в report-only, якщо блокування скриптів дорого коштуватиме. Коли inline-код потребує 'unsafe-inline', цей виняток треба назвати, а не називати політику строгою.

HSTS із includeSubDomains і preload вмикається лише тоді, коли кожен теперішній та майбутній субдомен готовий до HTTPS. Довідник MDN про HSTS пояснює вимоги preload і повільний відкат.

Динамічний сервіс має бути вузьким

У вигаданому прикладі Node-сервіс лічильника слухає лише loopback і отримує трафік через nginx. Публічний firewall не відкриває його порт. API приймає відомі slug, обмежує тіло запиту й відхиляє все інше.

PM2 або інший supervisor може перезапустити сервіс після виходу, але restart loop усе одно потребує логів та обмежень. Запис має бути атомарним, а небезпечному для паралельних increment JSON-сховищу знадобиться справжня база до зростання трафіку.

Найважливіше — деградація: після таймауту API сторінка показує статтю без числа, а не блокує контент.

Перевірка деплою йде шляхом запиту

Після контентної зміни перевірте той самий маршрут, яким іде відвідувач:

npm run build
curl -I https://portfolio.example/
curl -I https://portfolio.example/_astro/<hashed-file>.css
curl https://portfolio.example/sitemap-index.xml

Перевіряються статус, канонічні редиректи, кеш, заголовки безпеки та локалізовані сторінки. PM2 перезапускається лише після зміни сервісу чи його конфігурації. nginx — лише після успішного nginx -t. Restart за звичкою додає ризик, але нічого не доводить.

Коли керований хостинг кращий

Керований статичний хостинг варто обрати, коли preview-деплої, миттєвий відкат, глобальна доставка й менше обслуговування важливіші за контроль сервера. Для багатьох портфоліо це раціональна відповідь.

VPS має сенс, коли експлуатація сервера — свідома частина проєкту і є час на оновлення, моніторинг та відновлення. Урок не в тому, що селфхостинг завжди дешевший чи швидший. Урок у тому, що кожен додатковий шар повинен мати чітку роботу й сценарій відмови, який сайт переживе.