Руководство по установке и администрированию

Для того, кто ставит сайт на сервер и ведёт его содержимое. Ниже — вся схема: установка, настройка, обновление и работа в админке.

Как устроен сайт

Сайт — это ASP.NET Core (Razor Pages) на .NET 10, без базы данных и без JavaScript на публичных страницах. Весь контент лежит файлами в git-репозитории: репозиторий одновременно и база данных, и бэкап, и механизм обновления.

Разделы сайта модульные: набор, порядок, названия и адреса задаются в Content/site.json через админку «Структура». Один тип раздела можно включить несколько раз (например, два файловых архива); выключенный раздел пропадает из меню, его адреса отдают 404.

Установка на сервер

Требования: Ubuntu 26, от 1 ГБ RAM (обязательно swap 2 ГБ — иначе сборка на сервере может падать по памяти), .NET SDK 10, nginx. Домен (и поддомен www) должен указывать на сервер A-записями.

Самый простой путь — скрипт deploy/install.sh:

  1. Скопируйте репозиторий (или папку deploy/) на сервер.
  2. Заполните поля вверху скрипта: минимум SSH_USER (ваш SSH-пользователь) и ADMIN_PASSWORD (пароль входа в админку); остальные поля уже заполнены разумными значениями.
  3. Запустите:
    sudo bash deploy/install.sh

Скрипт делает всё: swap, ставит .NET SDK 10, создаёт системного пользователя viruzober и bare-репозиторий /srv/git/viruzober.git, ставит post-receive хук, systemd-сервис, nginx, создаёт файл секретов и запускает certbot (HTTPS). Повторный запуск безопасен: уже сделанные шаги пропускаются. Сервис стартует только после первого git push — хук рестартует его сам.

Если ставите вручную — те же шаги расписаны по порядку в deploy/README.md: swap, пользователь и каталоги, bare-репозиторий, хук, разрешение на рестарт сервиса через sudo visudo, systemd, nginx, certbot.

После установки — первый пуш с вашей машины:

git remote add origin ssh://ВАШ_ПОЛЬЗОВАТЕЛЬ@СЕРВЕР/srv/git/viruzober.git
git push -u origin main

Первый пуш запускает сборку на сервере (около минуты на одном ядре; в это время сайт может не отвечать), дальше — только перезапуск сервиса.

Настройка: пароль, почта, git

Секреты живут в одном файле на сервере — /srv/www/viruzober/appsettings.Production.json. В git он не попадает никогда (в .gitignore), права на файл — только у пользователя сервиса (chmod 600). Обновления через push этот файл не трогают.

{
  "Admin": { "Password": "ПРИДУМАЙТЕ_НАДЁЖНЫЙ_ПАРОЛЬ" },
  "Mail": { "To": "адрес@куда-приходят-письма" },
  "Git": {
    "RepositoryDir": "/srv/git/viruzober.git",
    "AuthorName": "Viruzober",
    "AuthorEmail": "admin@viruzober.com"
  }
}

Обновление сайта

Изменения кода публикуются только через git push: хук на сервере делает checkout, собирает проект и перезапускает сервис. Контент при этом читается прямо из рабочего дерева, так что правки админки видны сразу.

Админка на сервере коммитит в тот же bare-репозиторий, поэтому изменения не теряются при следующем пуше. Одно предостережение: checkout при пуше перетирает незакоммиченные изменения в дереве — админка коммитит сразу после каждого сохранения, окно маленькое, но не сохраняйте ничего в админке в момент пуша.

Вход в админку

Адрес — нестандартный (не /admin), задаётся при установке сайта и хранится в коде сервера — здесь намеренно не публикуется, это защита от автоматического перебора типовых адресов админки ботами. Пароль — из Admin:Password. Ссылка «Админка» в навигации сайта появляется после входа. На страницах админки меню сайта нет — сверху «Viruzober — админка» и ссылка «На сайт», навигация инструментов внутри.

Структура разделов

Админка → «Структура» — дерево всех разделов сайта в том порядке, в каком они стоят в меню. Что здесь можно:

Типы разделов:

ТипЧто этоНастройки
ГлавнаяТекст главной страницы (markdown) + список разделоводна, не создаётся и не удаляется
ПрограммыКаталог программ: категории, подкатегории, версии со скачиваниемпуть к Content/*.json
СтатьиСтатьи в markdown, сгруппированные в разделы-папкипуть к каталогу (например Content/articles)
Листинг файловФайловый архив с папками и скачиваниемпуть к каталогу
Обратная связьФорма, отправка письма через postfixбез контента
СтраницаОдна произвольная markdown-страницапуть к файлу .md
СсылкаПункт меню — переход на любой адресURL: /… — свой сайт, https://… — внешний
СервисОтдельное приложение на этом же домене (конвертер, редактор — что угодно), показывается во фрейме поверх шапки и подвала; под фреймом — ссылка открыть сервис в отдельной вкладке (запасной путь для скринридера)адрес сервиса /s/имя (выдаёт deploy/add-service.sh на сервере)

У «Ссылки» и «Сервиса» не бывает подразделов. Если экземпляров одного типа несколько, вверху страниц контента появляется выбор «Раздел» — переключение между ними.

Контент

Всё содержимое правится в админке; каждое сохранение коммитится в git.

Главная и страницы

Админка → «Главная» — текст главной страницы в markdown (заголовки, списки, ссылки, таблицы). Админка → «Страницы» — так же правятся страницы разделов типа «Страница» (например, «О сайте»).

Программы

Админка → «Программы»: категории, внутри — подкатегории (один уровень) и программы. У программы: название, краткое описание, полное описание (markdown) и таблица версий. Каждая версия — это версия, дата, имя файла, размер и заметки об изменениях. Сам файл кладётся в wwwroot/downloads/ (в поле указывается только имя файла, не путь). На странице программы версии показываются таблицей со ссылками «Скачать».

Статьи

Админка → «Статьи»: статьи в markdown, сгруппированные в разделы (как папки). Каждая статья — файл Content/articles/…/*.md с шапкой в формате YAML:

---
title: Название статьи
date: 2026-08-22
description: Краткое описание (показывается в списке)
tags: [первый, второй]
---

Текст статьи в markdown.

В статьях бывают картинки, аудио и видео. Файлы загружаются в админке (правка статьи → «Медиафайлы»), а в тексте на них ссылаются единым синтаксисом ![описание](media:имя-файла) — по расширению сайт сам покажет изображение, плеер или ссылку на скачивание. Описание у картинок обязательно (его озвучивает скринридер).

Файлы

Админка → «Файлы»: папки, загрузка нескольких файлов сразу, переименование и удаление. На сайте раздел отдаёт листинг папок и скачивание файлов. Имена файлов и папок: без / и \, не . и .., не начинаются с точки (такие файлы скрыты из листинга).

Поиск

Форма в шапке ищет по программам, статьям (включая текст), файлам и страницам — только по включённым разделам.

Git и бэкапы

Локальная разработка

На своей машине сайт поднимается одной командой из каталога репозитория:

dotnet run

http://localhost:5000. Адрес админки локально — тот же секретный путь, что и на сервере (см. deploy/README.md в репозитории), тестовый пароль — dev-password (задан в appsettings.Development.json, используется только для разработки; на сервере пароль свой — в appsettings.Production.json). Контент читается из файлов при каждом запросе: файл, положенный в Content/ вручную, виден сразу, перезапуск не нужен.

Админка с NVDA

Все формы подписаны, сообщения об ошибках и подтверждениях озвучиваются автоматически (в NVDA для этого должна быть включена настройка «Сообщать динамические изменения содержимого» — она включена по умолчанию). Отдельно — дерево в «Структуре»:

Лучше всего сайт работает в Firefox с последней версией NVDA.