Свой блог без лишней боли: почему мы выбрали WriteFreely и что с Instant View

1) Боль: хватит жить на чужом Telegraph
Telegraph классный для быстрых заметок, но это чужой сервис. Нет контроля над доменом, нет нормального RSS, картинки лежат «где-то там», а аналитику нельзя встроить. Для «Цифрового дворника» хотелось полноценный блог, которым мы управляем сами.
2) Что хотели от платформы
- self-hosted без внешних SaaS;
- Markdown-редактор;
- один Go-бинарник + SQLite (без MySQL/PostgreSQL);
- single-user режим и аскетичный UI без отвлекающих «порталов»;
- HTTPS через Caddy (Let's Encrypt);
- картинки — на своём paste-хостинге (paste.example.ru);
- каталог по тегам и RSS из коробки;
- веб-аналитика Umami (umami.example.ru);
- в Telegram-канал — только превью с обложкой и аннотацией, читать — на сайте (articles.example.ru).
3) Альтернативы и почему не они (кратко)
- Ghost — мощно, но стек Node + внешняя БД, тяжеловато ради одного блога.
- WordPress — перебор по функциональности и операционным хлопотам.
- Hugo/Jekyll — требуют сборки/деплоя, нет живого редактора в браузере.
- Notion/Obsidian Publish — не self-hosted и/или платно/закрыто.
- Telegraph — оставили запасным вариантом для набросков, но не для основного блога.

4) Почему WriteFreely
- один бинарник на Go;
- хранение в SQLite;
- single-user режим, минимализм;
- Markdown и RSS из коробки;
- есть HTTP API для автопубликации из пайплайна.
5) Как ставили (кратко)
- LXC-контейнер с systemd и выделенным пользователем приложения;
- сервис writefreely.service, автозапуск и перезапуск при падениях;
- Caddy как reverse_proxy перед приложением + автоматический Let's Encrypt;
- регистрация и федерация отключены (single-user блог без чужих аккаунтов).
6) Грабли по пути — только то, что реально встретили
writefreely --config— это интерактивный конфигуратор, а не путь к файлу. В юните systemd нужен флаг-c /opt/writefreely/config.ini, иначе сервис «уходит» в диалоговый режим и не стартует.- Бинд на
127.0.0.1+ reverse proxy с другого хоста = 502. Если прокси живёт вне контейнера с приложением, слушаем внутренний IP (например,10.0.x.x:8080), а в Caddy проксируем именно на него, а не на loopback. - API v0.17.2 игнорирует поле
appearance(режим тизеров на главной). Пришлось сделать анонсы чистым CSS (ограничение высоты + затухание), без участия API.
7) Что не получилось пока — Instant View
Встроенный редактор Telegram (instantview.telegram.org) сейчас не может забрать страницу блога из РФ: «Can't fetch page». Внешний входящий трафик на 80/443 до лабы режется, а IV-редактор ходит снаружи, поэтому он банально не видит наш сайт. Сам шаблон (XPath) готов и лежит в проекте — как только появится доступ снаружи (или настроим прокси), подключим IV и вернём красивый ⚡️-превью в канале. Это ограничение сети, а не блога.

8) Итог
Теперь у нас свой аккуратный блог на articles.example.ru, а в Telegram остаются лаконичные превью. Картинки — с нашего paste.example.ru, каталог — по тегам, RSS работает, аналитику даёт umami.example.ru. Минимум движущихся частей, максимум контроля.