Outline на сервере: частые ошибки и решения
Outline — быстрая корпоративная вики с Markdown-редактором и хорошим поиском, живая альтернатива Notion для команд, которым нужен self-hosted вариант. Ставится она через Docker Compose быстро, но именно там, где документация экономит слова — авторизация, хранилище файлов, почта — и начинаются проблемы. Ниже — конкретные ошибки, с которыми реально сталкиваются при развёртывании Outline на своём сервере, и как их закрыть.
Содержание
- Контейнер стартует и сразу падает
- OAuth не даёт войти: redirect_uri mismatch
- Загрузка файлов и картинок не работает (S3)
- Письма не приходят: инвайты, сброс пароля, уведомления
- Redis и очереди: медленный поиск, зависшие задачи
- Reverse proxy: 502, вебсокеты не подключаются, гигантские загрузки рвутся
- База данных: миграции и бэкапы
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Контейнер стартует и сразу падает
Самая частая ситуация: docker compose up -d отрабатывает, но через несколько секунд контейнер outline уходит в Restarting. Смотрим логи:
docker compose logs outline --tail=100
Три типичные причины:
- Не сгенерирован
SECRET_KEY/UTILS_SECRET. Outline требует два случайных hex-ключа по 32 байта каждый. Пустые или одинаковые значения — контейнер падает с ошибкой валидации на старте.
openssl rand -hex 32 # для SECRET_KEY
openssl rand -hex 32 # для UTILS_SECRET, значение должно отличаться
- Postgres ещё не готов, а Outline уже пытается подключиться. Docker Compose по умолчанию не ждёт готовности базы, только запуск контейнера. Решение — healthcheck и
depends_on: condition: service_healthy:
services:
postgres:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U outline"]
interval: 5s
timeout: 5s
retries: 10
outline:
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
URLв.envне совпадает с реальным доменом (или указан сhttpвместоhttps, или с завершающим слэшем). Outline сверяет этот параметр при формировании cookie и redirect-адресов OAuth — расхождение ломает не запуск, а именно вход после логина.
OAuth не даёт войти: redirect_uri mismatch
Outline не имеет собственной формы логина «email + пароль» из коробки — только сторонние провайдеры (Google, Slack, Microsoft, GitHub через community-сборки или generic OIDC). Самая частая ошибка на этом этапе — Error 400: redirect_uri_mismatch от Google.
Причина почти всегда одна: в консоли провайдера указан один redirect URI, а Outline формирует другой. Проверьте три вещи одновременно:
URLв.env— это ровно тот домен, с которого открывается вики (https://wiki.example.com, без слэша в конце);- в Google Cloud Console → Credentials → OAuth 2.0 Client IDs redirect URI указан как
https://wiki.example.com/auth/google.callback(для Slack —/auth/slack.callback, для generic OIDC —/auth/oidc.callback); GOOGLE_CLIENT_IDиGOOGLE_CLIENT_SECRET(или аналоги для другого провайдера) не содержат случайных пробелов — при копировании из консоли в.envэто встречается чаще, чем кажется.
Для generic OIDC (например, Keycloak, Authentik или Zitadel — актуальный вариант, если не хотите завязываться на Google) дополнительно нужны:
OIDC_CLIENT_ID=outline
OIDC_CLIENT_SECRET=...
OIDC_AUTH_URI=https://auth.example.com/application/o/authorize/
OIDC_TOKEN_URI=https://auth.example.com/application/o/token/
OIDC_USERINFO_URI=https://auth.example.com/application/o/userinfo/
OIDC_USERNAME_CLAIM=preferred_username
OIDC_DISPLAY_NAME=SSO
OIDC_SCOPES="openid profile email"
Если провайдер выдаёт токен, но Outline создаёт пользователя без имени или email — проверьте OIDC_USERNAME_CLAIM: часто в нём указывают sub (просто ID) вместо реального claim с именем.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверЗагрузка файлов и картинок не работает (S3)
Outline с 2023 года требует S3-совместимое хранилище для вложений — локальную файловую систему как storage backend разработчики убрали из официальной сборки. Без корректного S3 вставка изображений в документ либо зависает на «Uploading…», либо падает с ошибкой доступа.
Минимальный рабочий набор переменных:
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
AWS_REGION=us-east-1
AWS_S3_UPLOAD_BUCKET_URL=https://s3.example.com
AWS_S3_UPLOAD_BUCKET_NAME=outline-uploads
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private
Если поднимаете собственный S3-совместимый сервис (MinIO — рабочий вариант, не нужно платить внешнему провайдеру за объектное хранилище), обратите внимание на три момента:
AWS_S3_FORCE_PATH_STYLE=trueобязателен для MinIO — без него запросы уходят на несуществующий virtual-hosted домен видаbucket.s3.example.com;- бакет должен существовать заранее, Outline его не создаёт;
- CORS на бакете должен разрешать origin вашего домена вики, иначе браузер молча блокирует загрузку скриншотов при вставке через буфер обмена.
Если MinIO крутится в соседнем контейнере на том же сервере — разбирали отдельно, что именно там ломается чаще всего, в статье про MinIO на сервере: частые ошибки и решения.
Письма не приходят: инвайты, сброс пароля, уведомления
Outline использует SMTP только для двух вещей: приглашения новых участников и (опционально) email-уведомлений. Без корректного SMTP не критично для работы вики, но команда не сможет пригласить коллег ссылкой на почту.
SMTP_HOST=smtp.yourmail.com
SMTP_PORT=587
SMTP_USERNAME=noreply@example.com
SMTP_PASSWORD=...
SMTP_FROM_EMAIL=noreply@example.com
SMTP_TLS_CIPHERS=
SMTP_SECURE=false
Частая ошибка — SMTP_SECURE=true при порте 587. Порт 587 — это STARTTLS, а не implicit TLS: там SMTP_SECURE должен быть false (шифрование включается по протоколу после подключения). Implicit TLS (SMTP_SECURE=true) — это порт 465. Перепутанная пара порт/флаг — самая типичная причина тихого падения писем без внятной ошибки в логах.
Если письма уходят, но попадают в спам — проверьте SPF/DKIM/DMARC для домена, с которого шлёте SMTP_FROM_EMAIL. Это отдельная настройка на уровне DNS, к Outline отношения не имеющая, но именно она чаще всего оказывается причиной «письмо не пришло» на практике.
Redis и очереди: медленный поиск, зависшие задачи
Outline держит в Redis очереди фоновых задач (индексация для поиска, экспорт документов, обработка вебхуков) и WebSocket-подписки для live-редактирования. Если Redis недоступен или падает, симптомы не всегда очевидны:
- поиск по вики находит старые версии документов или не находит новых вообще — переиндексация не выполнилась;
- совместное редактирование в реальном времени работает, но без индикатора «кто сейчас редактирует» — это тоже завязано на Redis pub/sub;
- при удалении/восстановлении коллекций документы «зависают» в промежуточном статусе.
Проверка простая:
docker compose exec redis redis-cli ping
# должно вернуть PONG
docker compose logs outline | grep -i redis
Если Redis перезапускался без --appendonly yes и без volume под /data, очереди фоновых задач теряются при каждом рестарте контейнера — обязательно монтируйте persistent volume даже для инстанса Redis, который вы считаете «временным кэшем».
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
Reverse proxy: 502, вебсокеты не подключаются, гигантские загрузки рвутся
Outline за Nginx или Traefik — стандартная схема, но есть три специфичных для него нюанса, которые не всплывают в общих гайдах по reverse-proxy.
WebSocket не проксируется. Совместное редактирование и live-обновления идут через WebSocket-соединение. Без явных заголовков Upgrade Nginx рвёт это соединение — редактор откатывается в режим без realtime-синхронизации, что выглядит как «баг», а не как проблема конфигурации:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 86400;
}
Последняя строка — proxy_read_timeout — важна отдельно: дефолтные 60 секунд Nginx рвут долгоживущие WebSocket-соединения, и пользователи видят разрывы связи каждую минуту при простое без активности.
Большие вложения падают с 413. Дефолтный лимит Nginx на тело запроса — 1 МБ, чего хватает на текст, но не на скриншот с ретина-дисплея или PDF-вложение:
client_max_body_size 50m;
Заголовок X-Forwarded-Proto не доходит до приложения — тогда Outline генерирует ссылки на http:// даже за HTTPS-терминацией, и браузер блокирует часть контента как mixed content. Проверьте, что заголовок выставлен именно на уровне location, а не только на уровне server — при нескольких вложенных proxy_pass (например, Traefik перед Nginx) он теряется на промежуточном хопе.
Общий разбор ошибок настройки Nginx как reverse-proxy — в статье Nginx как reverse-proxy на сервере: частые ошибки и решения, там про заголовки и таймауты подробнее вне контекста конкретно Outline.
База данных: миграции и бэкапы
Postgres для Outline — не «просто база», в неё пишутся не только документы, но и версии правок (revision history), поэтому она растёт быстрее, чем кажется на старте, особенно если команда активно правит документы.
Ошибка, которая всплывает при обновлении версии Outline — контейнер падает на старте с чем-то вроде relation "..." does not exist. Обычно это означает, что миграции не применились автоматически (при рестарте после docker compose pull образ меняется, а команда запуска — нет). Явный прогон миграций перед стартом:
docker compose run --rm outline yarn db:migrate
Бэкап делайте на уровне Postgres, а не файлов контейнера — pg_dump в связке с cron-задачей, вынесенной за пределы контейнера:
docker compose exec -T postgres pg_dump -U outline outline | gzip > outline_$(date +%F).sql.gz
Если база уже разрослась и хочется системного подхода к настройке самого Postgres под нагрузку, а не только к бэкапам — пригодится статья PostgreSQL на сервере: частые ошибки и решения.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли запустить Outline без S3, чисто на локальном диске?
Официально — нет, с 2023 года код для локального file storage удалён из основной ветки. Обходной путь — поднять MinIO в соседнем контейнере на том же сервере, тогда S3 API есть, а данные физически остаются у вас.
Почему после логина через Google сразу выкидывает обратно на страницу входа?
Чаще всего — рассинхрон URL в .env с реальным доменом или неверный SECRET_KEY/UTILS_SECRET (если их поменяли после того, как пользователи уже залогинились, все существующие сессии и cookie становятся невалидными).
Сколько ресурсов реально нужно для команды из 20-30 человек?
Как ориентир — 2 vCPU и 4 ГБ RAM с запасом хватает на Outline + Postgres + Redis для такой команды при умеренной активности; точные цифры зависят от объёма вложений и частоты правок, стоит проверить на своей нагрузке.
Outline и Outline VPN — это одно и то же?
Нет, это два разных продукта с совпадающим названием: вики-система Outline от Wiki (Getoutline.com) и Outline VPN (Outline Server/Manager) от Jigsaw/Google — они не связаны и не имеют общего кода, легко перепутать при поиске документации.
Можно ли перенести Outline с одного сервера на другой без потери истории правок?
Да — переносите Postgres (pg_dump/pg_restore) и содержимое S3-бакета целиком, историю ревизий это сохраняет полностью, поскольку она хранится в базе, а не в файлах.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →