Перейти к содержанию
  1. Статьи/

Суверенная операционка без Битрикса: AI-ready стек на одном сервере

·1857 слов·9 минут

Суверенная операционка без Битрикса: AI-ready стек на одном сервере #

Один сервер. Один сисадмин. Полный контроль над данными и готовность к эре AI. Разбор архитектуры для компаний, которые устали от SaaS-зависимостей и хотят нормальную операционку.


Давайте честно: бухгалтерия — святое, а всё остальное — архитектурный кринж #

Сразу расставим точки над «i». 1С:Бухгалтерия — это монополия, и это нормально. Она зашита в ДНК российского налогового кодекса. Пытаться заменить её на Open Source в SMB-компании — это мазохизм. Обычно в малом и среднем бизнесе бухгалтерия вообще на аутсорсе: они работают в своей 1С/СБИС, и это правильно.

Мы сюда не за этим. Мы сюда за тем, чтобы построить операционку компании: управление задачами, база знаний, учёт активов, регламенты, онбординг, юридические шаблоны. И вот тут начинается архитектурный ужас.

Вариантов обычно два(не считая более узких SaaS), и оба плохие:

  1. Битрикс24 — SaaS-комбайн, где при блокировке аккаунта, уходе из облака или просто изменении тарифа компания теряет всю корпоративную память. Плюс вендор-лок: никуда не уедешь с их данными без слёз.
  2. 1С:Предприятие для операционки (Документооборот, Задачи) — фреймворк для бэкофиса, натянутый на веб-интерфейс уровня 2005 года. Любой чих — звонок франчайзи и почасовая оплата.

А теперь вопрос: что если вместо этого за 3 года вы потратите ~105 тысяч рублей + один компьютер, получите полный контроль над данными и бонусом — AI-ready стек, который умеет отвечать на вопросы сотрудников по вашей же внутренней документации?


Философия: Суверенная операционка #

Парадигма та же, что и в моей первой статье про K3s-кластер: моё железо, мои правила, мои модели.

Для SMB-компании это значит:

  • Layer 1-2: свой сервер в офисе или арендованный в ДЦ, не виртуалка провайдера
  • Layer 3-4: свой DNS (Unbound), свой firewall, своя сеть
  • Layer 7: свои сервисы вместо SaaS-подписок
  • AI Layer: локальная LLM + RAG по документам компании, без отправки данных в OpenAI/Anthropic/Alibaba/Deepseek

Важный нюанс: вся обвязка — открытая и интегрируемая. У каждого сервиса есть REST API или вебхуки. Если вдруг понадобится связать таск-трекер с 1С бухгалтера для автогенерации счетов — это делается за вечер, а не через интегратора за 50к.

Ключевое отличие от первой статьи: здесь не нужен Kubernetes. Один сервер, Docker Compose (или Podman), и всё. Сисадмин средней руки справится.


Архитектура: один сервер, шесть сервисов #

flowchart TB subgraph Server["Один сервер (16GB RAM / 8 vCPU)"] direction TB subgraph Edge["Edge Layer"] Traefik["Traefik :80/:443
Reverse Proxy + TLS"] Unbound["Unbound :53
Recursive DNS"] AdGuard["AdGuard Home
DNS Filtering"] end subgraph Apps["Application Layer"] Kaneo["Kaneo
Task Management"] Wiki["Wiki.js
Knowledge Base"] SnipeIT["Snipe-IT
Asset Management"] end subgraph Auth["Auth Layer"] Keycloak["Keycloak
SSO / OIDC"] end subgraph Data["Data Layer"] PG["PostgreSQL 16
Shared DB"] VK["Valkey 8
Cache/Sessions"] Qdrant["Qdrant
Vector DB"] end subgraph AI["AI Layer"] Ollama["Ollama
Local LLM"] end end Client["Сотрудники / Клиенты"] --> Traefik Traefik --> Apps Traefik --> Keycloak Apps --> Auth Apps --> Data Keycloak --> Data Wiki --> AI AI --> Qdrant AdGuard --> Unbound style Server fill:#f0f9ff,stroke:#2563eb,stroke-width:2px style Edge fill:#fef3c7,stroke:#d97706 style Apps fill:#dcfce7,stroke:#16a34a style Auth fill:#fee2e2,stroke:#dc2626 style Data fill:#e0e7ff,stroke:#4f46e5 style AI fill:#fae8ff,stroke:#a855f7

Почему именно эти сервисы и что они заменяют в популярном SaaS:

РольСервисЗачемАльтернатива в Битрикс24
Управление задачамиKaneoСовременный Kanban, MIT-лицензия«Задачи и проекты»
База знанийWiki.jsMarkdown, поиск, OIDC-авторизация«База знаний»
Учёт активовSnipe-ITЖелезо, лицензии, расходникиОтсутствует (или через CRM-кастомизацию)
Единый входKeycloakSSO во все сервисыВнутренняя авторизация Битрикс24
Приватный DNSUnboundРекурсор без телеметрии
Сетевой ad-blockAdGuard HomeБлокировка трекеров на уровне сети

Бонус — AI-ready слой, которого в принципе нет у вендоров:

КомпонентЗачем
OllamaЛокальная LLM (Llama 3.1, Qwen, DeepSeek)
QdrantВекторная БД для эмбеддингов документов
Wiki.js + RAGПоиск по базе знаний компании через LLM

Docker Compose: рабочий скелет #

Файл docker-compose.yml, который можно скопировать и запустить:

version: '3.8'

networks:
  office:
    driver: bridge

volumes:
  postgres_data:
  valkey_data:
  keycloak_data:
  wiki_data:
  snipeit_data:
  kaneo_data:
  qdrant_data:
  ollama_data:

services:
  # === REVERSE PROXY ===
  traefik:
    image: traefik:v3.7
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=ssl@company.local"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    restart: unless-stopped

  # === SHARED DATABASES ===
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh
    restart: unless-stopped

  valkey:
    image: valkey/valkey:8-alpine
    volumes:
      - valkey_data:/data
    restart: unless-stopped

  # === SSO ===
  keycloak:
    image: quay.io/keycloak/keycloak:25.0
    command: start
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: postgres
      KC_DB_PASSWORD: ${DB_PASSWORD}
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
      KC_HOSTNAME: sso.company.local
      KC_PROXY_HEADERS: xforwarded
      KC_HTTP_ENABLED: "true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.keycloak.rule=Host(`sso.company.local`)"
      - "traefik.http.routers.keycloak.entrypoints=websecure"
      - "traefik.http.routers.keycloak.tls.certresolver=letsencrypt"
    depends_on: [postgres]
    restart: unless-stopped

  # === WIKI ===
  wiki:
    image: requarks/wiki:2
    environment:
      DB_TYPE: postgres
      DB_HOST: postgres
      DB_PORT: 5432
      DB_NAME: wiki
      DB_USER: postgres
      DB_PASS: ${DB_PASSWORD}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wiki.rule=Host(`wiki.company.local`)"
      - "traefik.http.routers.wiki.entrypoints=websecure"
      - "traefik.http.routers.wiki.tls.certresolver=letsencrypt"
    depends_on: [postgres]
    restart: unless-stopped

  # === ASSET MANAGEMENT ===
  snipeit:
    image: snipe/snipe-it
    environment:
      DB_CONNECTION: pgsql
      DB_HOST: postgres
      DB_DATABASE: snipeit
      DB_USERNAME: postgres
      DB_PASSWORD: ${DB_PASSWORD}
      APP_URL: https://assets.company.local
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.snipeit.rule=Host(`assets.company.local`)"
      - "traefik.http.routers.snipeit.entrypoints=websecure"
      - "traefik.http.routers.snipeit.tls.certresolver=letsencrypt"
    volumes:
      - snipeit_data:/var/lib/snipeit
    depends_on: [postgres]
    restart: unless-stopped

  # === TASKS ===
  kaneo:
    image: ghcr.io/usekaneo/api:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.kaneo.rule=Host(`tasks.company.local`)"
      - "traefik.http.routers.kaneo.entrypoints=websecure"
      - "traefik.http.routers.kaneo.tls.certresolver=letsencrypt"
    volumes:
      - kaneo_data:/app/data
    restart: unless-stopped

  # === DNS ===
  unbound:
    image: mvance/unbound:latest
    ports:
      - "53:53/tcp"
      - "53:53/udp"
    volumes:
      - ./unbound/unbound.conf:/opt/unbound/etc/unbound/unbound.conf:ro
    restart: unless-stopped

  # === AD BLOCK ===
  adguard:
    image: adguard/adguardhome
    ports:
      - "3000:3000/tcp"
    volumes:
      - ./adguard/work:/opt/adguardhome/work
      - ./adguard/conf:/opt/adguardhome/conf
    restart: unless-stopped

  # === AI LAYER ===
  ollama:
    image: ollama/ollama
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    restart: unless-stopped

  qdrant:
    image: qdrant/qdrant
    volumes:
      - qdrant_data:/qdrant/storage
    restart: unless-stopped

И init-db.sh для создания баз:

#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
    CREATE DATABASE keycloak;
    CREATE DATABASE wiki;
    CREATE DATABASE snipeit;
    CREATE DATABASE kaneo;
EOSQL

AI-ready слой: как это работает #

Вот где наш стек реально выигрывает у любого SaaS.

sequenceDiagram participant User as Сотрудник participant UI as Чат-интерфейс participant RAG as RAG Pipeline participant Qdrant as Qdrant (Vectors) participant LLM as Ollama (Local LLM) User->>UI: "Какой порядок согласования договора с поставщиком?" UI->>RAG: Запрос RAG->>RAG: Эмбеддинг запроса RAG->>Qdrant: Similarity search Qdrant-->>RAG: Топ-5 релевантных чанков из Wiki.js RAG->>LLM: Prompt + контекст LLM-->>RAG: Ответ RAG-->>UI: Финальный ответ UI-->>User: Ответ + ссылки на источники в Wiki

Как это работает:

  1. Wiki.js экспортирует все страницы в Markdown
  2. Скрипт чанкает документы (по 512 токенов) и считает эмбеддинги через nomic-embed-text
  3. Эмбеддинги складываются в Qdrant
  4. При вопросе — similarity search по векторам, контекст идёт в LLM
  5. LLM отвечает на основе ваших документов, а не галлюцинирует из интернета

Что это даёт компании (именно операционке, а не бухгалтерии):

  • Юристы спрашивают про регламенты → получают ответ со ссылкой на пункт типового договора
  • Сейлзы спрашивают про скрипты и ценообразование → получают ответ из внутреннего playbook’а
  • HR и новички онбордятся в 3 раза быстрее: “как оформить пропуск”, “где взять VPN”, “как согласовать отпуск”
  • Менеджеры получают выжимки из регламентов без чтения 50-страничных PDF
  • Никакие данные не покидают периметр компании

Бухгалтерия в этом не участвует — у них своя 1С, свои регламенты и свои риски. Не смешиваем.

Стоимость: одна RTX 3060 12GB (~25к ₽) позволяет гонять Llama 3.1 8B с скоростью 20-30 токенов/сек. Для компании из 20 человек этого достаточно.


Математика выгоды: Self-hosted vs Битрикс24 (3 года) #

Бухгалтерию из сравнения убираем — она вне конкуренции и живет своей жизнью на аутсорсе. Сравниваем операционку: наш стек против типичного сетапа на Битрикс24 с модулями для команды из 20 человек.

Затраты на Битрикс24 для 20 человек (3 года):

  • Тариф «Профессиональный» (нужен для базы знаний и CRM): ~4 849 ₽/мес × 36 = ~175к ₽
  • Дополнительные модули (Задачи+, Расширенная база знаний): ~60к ₽
  • Внедрение/кастомизация от партнёра: от 80к ₽
  • ИТОГО: ~315к ₽ минимум
  • И вы остаётесь в SaaS-зависимости с закрытым кодом и невозможностью локальной LLM

Затраты на self-hosted стек (3 года):

  • Сервер (Dell R740 б/у или мини-ПК): 60-80к ₽
  • GPU для LLM (RTX 3060): 25-40к ₽
  • Электричество (300 Вт × 3 года): ~20-25к ₽
  • Домен + SSL: 2000 ₽ (Let’s Encrypt)
  • ИТОГО: ~107к ₽

Экономия: ~208к ₽ за 3 года + бонусом получаете AI-ready инфраструктуру и полный контроль над данными, чего у SaaS нет в принципе.

%%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#2563eb', 'primaryTextColor': '#1a1a1a', 'primaryBorderColor': '#1e40af', 'lineColor': '#1a1a1a', 'secondaryColor': '#dc2626', 'tertiaryColor': '#16a34a', 'xyChart': { 'titleColor': '#1a1a1a', 'xAxisTitleColor': '#1a1a1a', 'xAxisLabelColor': '#1a1a1a', 'xAxisLineColor': '#1a1a1a', 'xAxisTickColor': '#1a1a1a', 'yAxisTitleColor': '#1a1a1a', 'yAxisLabelColor': '#1a1a1a', 'yAxisLineColor': '#1a1a1a', 'yAxisTickColor': '#1a1a1a', 'plotColorPalette': '#2563eb, #dc2626, #16a34a' } } }}%% xychart-beta title "TCO операционки за 3 года (тыс. ₽)" x-axis ["Self-hosted + AI", "Битрикс24 + внедрение"] y-axis "Затраты (тыс. ₽)" 0 --> 400 bar [105, 315]

Подводные камни #

Я не буду делать вид, что это просто. Вот реальные грабли:

1. Keycloak — Java-монстр #

Keycloak жрёт 512MB–1GB RAM просто за факт существования. Для компании из 20 человек это overkill.(Хотя для параноиков-самое то.)

Решение: рассмотреть Authentik (Python, легче в 3 раза) или Dex (OIDC-провайдер, почти не ест). Если у вас меньше 10 пользователей — Keycloak не нужен вообще, хватит базовой авторизации в каждом сервисе.

2. Бэкапы volumes #

Если не настроить бэкап /var/lib/docker/volumes — потеряете всё при смерти диска.

Решение: borgmatic + ежедневные бэкапы на внешний MinIO/S3. Стратегия 3-2-1: 3 копии, 2 разных носителя, 1 копия оффсайт.

3. Watchtower — зло для продакшена #

Многие ставят watchtower для автообновления образов. Это риск: образ может сломать совместимость.

Решение: cron + ручные обновления раз в месяц после чтения changelog’ов.

4. Unbound vs AdGuard Home #

Это не конкурирующие, а взаимодополняющие сервисы. AdGuard Home — DNS-форвардер с фильтрами, Unbound — полноценный рекурсор.

Правильная схема: клиенты → AdGuard Home (фильтрация) → Unbound (рекурсия) → root DNS.

5. PostgreSQL на всех — это риск #

Все сервисы в одной инстансе Postgres — удобно, но один падающий запрос может повлиять на всех.

Для продакшена: отдельные инстансы Postgres для критичных сервисов (Snipe-IT отдельно, Keycloak отдельно).


Docker vs Podman: что выбрать #

Для этой статьи я использовал Docker Compose — он знаком большинству сисадминов. Но есть альтернатива: Podman.

Почему Podman может быть лучше:

  • Rootless-контейнеры (сисадмин параноит — правильно делает)
  • Нет демона (нет единой точки отказа)
  • Drop-in замена: podman-compose up -d работает с тем же docker-compose.yml

Почему Docker может быть лучше:

  • Больше документации
  • docker-compose watch для live-reload при разработке
  • Привычнее для тех, кто пришёл из облаков

Для компании из 20 человек разницы почти нет. Выбирайте то, что знает ваш сисадмин.


План внедрения для сисадмина #

  1. День 1: Арендовать/купить сервер (16GB RAM минимум, 24GB если будет LLM)
  2. День 2: Debian 12 + Docker + Traefik, базовая настройка firewall
  3. День 3-5: Развернуть базовый стек (Postgres, Keycloak, Wiki.js)
  4. День 6-7: Настроить SSO, завести пользователей
  5. Неделя 2: Подключить Kaneo и Snipe-IT, перенести данные из Excel
  6. Неделя 3: Настроить Unbound + AdGuard Home, перевести клиентов
  7. Неделя 4: Настроить бэкапы через borgmatic
  8. Месяц 2: Внедрить AI-слой (Ollama + Qdrant + RAG)
  9. Постоянно: Документировать всё в Wiki.js (мета-уровень)

Заключение #

В 2026 году SaaS-монополии — не единственная опция для операционки SMB-компаний. Self-hosted стек на опенсорсе даёт:

  • Экономию ~210к ₽ за 3 года по сравнению с Битрикс24
  • Полный контроль над данными (никаких SaaS-вендоров)
  • AI-ready инфраструктуру, которой нет ни у одного коробочного решения
  • Бухгалтерия при этом спокойно работает в своей 1С на аутсорсе — без конфликтов и миграций

Цена — один сервер и один толковый сисадмин. Если у вашей компании есть и то, и другое — вы уже готовы.

Если интересно посмотреть на реальные конфиги Unbound, скрипт индексации Wiki.js в Qdrant, или обсудить архитектуру под ваш размер компании — залетайте в Telegram-канал. Там выложу ссылки на репозиторий с готовыми docker-compose и Ansible-плейбуками.

📬 Связаться со мной

Если у вас есть вопросы по инфраструктуре, предложения по сотрудничеству или просто хотите обсудить DevOps — пишите в Telegram.

📢Канал: кейсы и разное

Отвечаю в течение 24–48 часов. По консультационным вопросам — сразу с описанием задачи.