Wiki.js — открытая база знаний на Node.js, которая хранит страницы в PostgreSQL и разграничивает доступ через группы и правила путей. Для домашней лаборатории или команды из пяти-десяти человек это удобная замена папке с Markdown: появляется поиск, история версий и понятные права. Стабильной остаётся ветка 2.x, её и развернём в Docker.
Что даёт Wiki.js
- Полнотекстовый поиск работает на PostgreSQL с расширением pg_trgm, отдельный Elasticsearch не нужен.
- История версий и сравнение правок встроены, страницу можно вернуть к любому состоянию.
- Права задаются глобальными разрешениями и правилами по путям, вплоть до отдельной страницы.
- Вход через локальные учётные записи, LDAP/AD или OAuth2/OIDC, например Keycloak и Authentik; есть TOTP.
- Весь контент хранится в базе, поэтому резервная копия — это дамп PostgreSQL.
Ограничения тоже стоит знать заранее. Wiki.js не ставится в подкаталог: нужен отдельный домен или поддомен. Это приложение с фоновыми задачами, а не статический генератор, поэтому обновления лучше проверять на копии. Зато перенос на другой сервер сводится к дампу и восстановлению базы.
Развёртывание в Docker
Минимальная конфигурация — два контейнера: PostgreSQL 16 и сам Wiki.js. Пароль и имя базы вынесем в .env, чтобы не держать их в compose-файле.
mkdir -p /opt/wikijs && cd /opt/wikijs
cat > .env <<'EOF'
POSTGRES_DB=wikijs
POSTGRES_USER=wikijs
POSTGRES_PASSWORD=change-me-long
EOF
docker compose up -d
В compose-файле у базы должен быть healthcheck, иначе приложение стартует раньше PostgreSQL и падает с ошибкой подключения. Зависимость с condition: service_healthy решает это без ручных перезапусков.
services:
db:
image: postgres:16-alpine
env_file: .env
volumes:
- db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U wikijs -d wikijs"]
interval: 5s
retries: 10
wiki:
image: ghcr.io/requarks/wiki:2
init: true
depends_on:
db:
condition: service_healthy
env_file: .env
environment:
DB_TYPE: postgres
DB_HOST: db
DB_PORT: 5432
DB_NAME: wikijs
DB_USER: wikijs
DB_PASS: ${POSTGRES_PASSWORD}
ports:
- "127.0.0.1:3000:3000"
volumes:
db:
Порт привязан к localhost: наружу его отдаст nginx. После старта проверьте логи и откройте адрес в браузере. Первый запуск попросит создать администратора и указать адрес сайта — сразу пишите внешний URL, иначе ссылки в письмах и предпросмотре будут вести на localhost.
Группы и правила доступа
Модель прав состоит из четырёх частей: группы, пользователи, глобальные разрешения и правила страниц. Глобальное разрешение — главный выключатель: если в группе не включено read:pages, никакое правило страницы не даст читать материалы. Правила лишь уточняют, где именно действует разрешение.
Порядок применения определяется точностью пути, а не порядком строк в интерфейсе. Более конкретный путь перекрывает общий; при равной точности приоритет такой: «начинается с», «заканчивается на», регулярное выражение, точное совпадение. Если совпали и точность, и тип, запрет всегда сильнее разрешения.
Убедиться, что база отвечает и таблицы на месте, можно запросами:
docker compose exec db psql -U wikijs -d wikijs -c "select count(*) from pages;"
docker compose exec db psql -U wikijs -d wikijs -c "select email, name from users;"
Создайте группу Editors, включите ей read:pages, write:pages и read:assets, затем добавьте правило Allow для пути /team с типом «начинается с». Для закрытого раздела /team/salary добавьте отдельное правило Deny с точным совпадением — оно перекроет общее. Помните, что пути из двух букв, например /hr или /it, зарезервированы под языки и работать как раздел не будут.
Чтобы закрыть вики целиком, измените группу Guests: уберите у неё глобальные разрешения или замените стартовое правило Allow на Deny. После этого неавторизованный посетитель увидит только форму входа.
Nginx и HTTPS
Приложение слушает 3000-й порт, снаружи его закрывает обратный прокси. Для корректной работы редактора и загрузки файлов нужны заголовки Host и X-Forwarded-*, а также поддержка WebSocket.
server {
listen 443 ssl http2;
server_name wiki.example.com;
ssl_certificate /etc/letsencrypt/live/wiki.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wiki.example.com/privkey.pem;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Сертификат Let’s Encrypt выпускается только на публичное доменное имя. Для внутренней сети используйте сертификат от собственного удостоверяющего центра и раздайте корневой сертификат на клиентские машины — это честнее, чем приучать браузеры игнорировать ошибки TLS.
Резервное копирование
Поскольку страницы и вложения лежат в PostgreSQL, основной бэкап — логический дамп. Делайте его по расписанию и храните вне того же диска.
docker compose exec -T db pg_dump -U wikijs -Fc wikijs > wikijs-$(date +%F).dump
docker compose stop wiki
docker compose exec -T db dropdb -U wikijs wikijs
docker compose exec -T db createdb -U wikijs wikijs
docker compose exec -T db pg_restore -U wikijs -d wikijs < wikijs-2026-11-01.dump
docker compose start wiki
Перед восстановлением остановите приложение, иначе оно будет держать соединения и писать в базу. Дамп в формате -Fc сжимается и восстанавливается через pg_restore. Раз в месяц проверяйте копию на отдельной машине: дамп, который ни разу не разворачивали, сложно считать резервной копией.
Диагностика
- 502 от nginx: контейнер не поднялся. Смотрите docker compose ps и docker compose logs wiki.
- Ошибка подключения к базе: проверьте переменные DB_* и pg_isready внутри контейнера db.
- Поиск не находит страницы: убедитесь, что в базе доступно расширение pg_trgm, и проверьте настройки поиска в админке.
- Не загружаются файлы: проверьте client_max_body_size в nginx и лимиты выбранного модуля хранения.
- После обновления пустой экран: откатитесь на прежний тег образа и восстановите дамп, снятый перед обновлением.
Чек-лист
- Порт 3000 доступен только с localhost, снаружи работает HTTPS.
- У гостей нет прав на запись, регистрация закрыта.
- Администратор использует длинный пароль и TOTP.
- Дамп базы снимается ежедневно и хранится на другом носителе.
- Правила доступа проверены под тестовым пользователем, а не только под администратором.
Итог
Wiki.js даёт команде аккуратную базу знаний без тяжёлой инфраструктуры: PostgreSQL, контейнер и обратный прокси. Основная работа — не установка, а продуманная модель групп и правил. Начните с малого: две-три группы, явные пути, запрет всего лишнего для гостей. Затем добавьте резервное копирование и проверку восстановления. Такой портал переживёт смену сервера и не превратится в свалку документов с одинаковыми правами доступа.