Публикация 1С на веб-сервере: установка Apache, публикация базы, HTTPS и IIS

Публикация 1С на веб-сервере: Apache, IIS, SSL и Docker
Видео: Публикация 1С на веб-сервере: Apache, IIS, SSL и Docker

Публикация 1С на веб-сервере — это то, с чего начинается любая интеграция: веб-клиент в браузере, тонкий клиент через интернет, HTTP- и OData-сервисы, обмен с интернет-магазином, мобильное приложение. Пока база доступна только из локальной сети через толстый клиент, все эти сценарии закрыты. В этой статье я по шагам показываю, как поднять веб-сервер 1С на Apache и на IIS под Windows, как опубликовать базу вручную через httpd.conf (а не только галочками в Конфигураторе), и разбираю нюансы, которых нет в других инструкциях: как зашить логин прямо в конфиг Apache, как обойти CORS для HTTP-сервисов и как вынести Apache в Docker, оставив саму 1С на хосте.

Статья собрана из боевого конфига Apache, на котором у меня одновременно опубликованы десяток баз. Поэтому здесь не абстрактные примеры «It works», а те строки, которые реально работают в проде.

Что такое публикация 1С на веб-сервере и зачем она нужна

Публикация — это когда информационная база 1С становится доступна по HTTP. Платформа 1С не умеет сама слушать порт 80: ей нужен веб-сервер (Apache или IIS), а связь между веб-сервером и платформой обеспечивает специальный модуль расширения веб-сервера — библиотека, которую ставят вместе с платформой.

После публикации по одному и тому же адресу становятся доступны сразу несколько вещей:

  • Веб-клиент — полноценная 1С прямо в браузере, без установки.
  • Тонкий клиент через интернет — то же приложение 1С, но подключается к базе по HTTP/HTTPS, а не по файловому доступу.
  • HTTP-сервисы и OData — программные точки входа для интеграций: интернет-магазин, мобильное приложение, внешний сервис на Python или Node.js.

Всё это работает через один механизм публикации. Разница только в галочках и в тонкой настройке конфига.

Как устроена публикация: модуль, default.vrd и обработчик

Прежде чем нажимать кнопки, полезно понимать, что именно происходит под капотом. Публикация базы 1С на любом веб-сервере — это три вещи:

  1. Модуль веб-сервера 1С загружается в веб-сервер. Для Apache это wsap24.dll (Windows) или wsap24.so (Linux), для IIS — wsisapi.dll. Разрядность модуля обязана совпадать с разрядностью платформы 1С.
  2. В папке базы появляется файл default.vrd — дескриптор публикации: он говорит, какая база публикуется, под каким именем и какие сервисы включены.
  3. В конфиге веб-сервера появляется блок, который на нужном URL-пути включает обработчик 1c-application и указывает на этот default.vrd.

Когда браузер стучится по адресу публикации, Apache видит SetHandler 1c-application, передаёт запрос модулю 1С, модуль читает default.vrd, открывает базу и возвращает веб-клиент. Всё. Дальше — детали каждого шага и ошибки, которые на этих шагах вылезают.

Apache или IIS: что выбрать для 1С

Оба варианта рабочие, и оба 1С поддерживает официально. Коротко: IIS уже встроен в Windows Server и роднее экосистеме Microsoft; Apache кросс-платформенный (тот же конфиг работает и на Linux), правится обычным текстом и легче ложится в Docker. Если вам нужны тонкие вещи — свои заголовки, CORS, зашитая авторизация, несколько баз с разными настройками — на Apache это делается быстрее, потому что всё описывается парой строк в текстовом файле.

Ниже я подробно разбираю сначала Apache (основной сценарий), а потом IIS — со всеми ошибками, которые встретятся по пути.

Установка веб-сервера Apache 2.4 под 1С

Скачивать Apache нужно той же разрядности, что и платформа 1С: если у вас 1С x64, то и Apache x64. Я беру сборки Apache Haus или Apache Lounge — для работы им нужен установленный Microsoft Visual C++ Redistributable соответствующей разрядности, иначе служба не стартует.

Дальше распаковываем архив в постоянную папку (у меня это D:/Server/Bin/Apache24) и правим главный конфиг conf/httpd.conf. Минимум, что нужно поменять:

# Корень, где лежит сам Apache. В Windows — только ПРЯМЫЕ слэши!
Define SRVROOT "D:/Server/Bin/Apache24"
ServerRoot "${SRVROOT}"

# Порт. По умолчанию 80, можно поставить любой — я держу 8080,
# чтобы не конфликтовать с другими сервисами.
Listen 8080

# Имя сервера — для локальной работы достаточно localhost.
ServerName localhost

# Папка, где будут лежать базы и сайты.
DocumentRoot "D:/www"
<Directory "D:/www">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

# Индексные файлы
<IfModule dir_module>
    DirectoryIndex index.php index.html index.htm
</IfModule>

Обратите внимание на слэши: в путях Apache под Windows пишут D:/www, а не D:\www — обратные слэши Apache не понимает. Это ошибка номер один у новичков.

После правки конфига ставим Apache службой. В сборках это делается командой из папки bin (от имени администратора):

httpd.exe -k install
httpd.exe -k start

Проверяем: открываем в браузере http://localhost:8080/. Если видите список каталога или свою индексную страницу — веб-сервер поднялся. Если служба не стартует, почти всегда причина одна из двух: занят порт (смените Listen) или не установлен нужный Visual C++ Redistributable.

Где скачать Apache и как разложить каталоги

Сам проект Apache распространяет только исходники — готовые бинарники под Windows собирают сторонние сборщики. Берите Apache Lounge или Apache Haus, ветку 2.4.x нужной разрядности. Разрядность обязана совпадать с платформой 1С: Apache x64 не загрузит 32-битный wsap24.dll, и наоборот.

Сайт Apache Lounge, раздел загрузки: сборки Apache 2.4 VC15 для Windows 64 и 32 бит

Структуру каталогов лучше задать сразу и осмысленно, а не распаковывать архив в «Загрузки». У меня это C:/Server/Bin/Apache24 — отдельная папка Server под весь веб-стек, внутри Bin для бинарников. Дальше туда же лягут PHP и MySQL, если они понадобятся.

Проводник: каталог C:\Server\Bin, куда переносится папка Apache24

Что именно менять в httpd.conf

Главный конфиг лежит в conf/httpd.conf. Правки точечные — ищем строку и меняем:

  • Define SRVROOT "c:/Apache24" → путь, куда вы распаковали Apache. Только прямые слэши — обратные Apache под Windows не понимает, это ошибка номер один.
  • #ServerName www.example.com:80ServerName localhost (для локальной работы этого достаточно).
  • DocumentRoot "${SRVROOT}/htdocs" → папка, где будут лежать сайты и публикации баз, например Z:/www. Тот же путь поменяйте и в блоке <Directory> ниже.
  • DirectoryIndex index.htmlDirectoryIndex index.php index.html index.htm, если рядом планируется PHP.
  • AllowOverride noneAllowOverride All — разрешает .htaccess, то есть переопределение настроек для отдельного подкаталога помимо общего конфига.
  • #LoadModule rewrite_module modules/mod_rewrite.so — снимите решётку. mod_rewrite преобразует URL по правилам-регуляркам, пригодится и для сайта рядом с базой.

Запуск службой Windows и проверка

Apache ставится службой одной командой из каталога bin (командная строка — от администратора):

httpd.exe -k install     # установить службу
httpd.exe -k start       # запустить
httpd.exe -k stop        # остановить
httpd.exe -k restart     # перезапустить после правки конфига
httpd.exe -k uninstall   # удалить службу

Возьмите за правило перед каждым перезапуском проверять синтаксис: httpd.exe -t на Windows, apachectl configtest на Linux. Команда покажет номер строки с ошибкой — это дешевле, чем уронить рабочую публикацию опечаткой и потом гадать, почему служба не поднимается.

Проверка: открываем http://localhost:8080/ — должна отдаться стартовая страница Apache или листинг каталога. В services.msc при этом висит служба Apache2.4 в статусе «Выполняется».

Страница Index of / по адресу localhost и служба Apache2.4 в оснастке «Службы» Windows

Если служба не стартует — почти всегда одно из двух: занят порт (смените Listen) или не установлен Microsoft Visual C++ Redistributable нужной разрядности.

Публикация базы: через Конфигуратор и вручную в httpd.conf

Самый простой способ — из Конфигуратора: Администрирование → Публикация на веб-сервере. Выбираете Apache, указываете папку и имя публикации (латиницей, строчными буквами), снимаете лишние галочки и жмёте «Опубликовать». 1С сама создаст default.vrd и допишет блок в httpd.conf.

Но я советую понимать, что именно она дописывает, — потому что руками это делается надёжнее, и только так можно добавить тонкие настройки. Вот минимальный боевой блок публикации базы:

# Модуль веб-сервера 1С — грузится один раз, путь под вашу версию платформы
LoadModule _1cws_module "C:/Program Files/1cv8/8.3.27.1989/bin/wsap24.dll"

# Публикация базы по адресу /ut11
Alias "/ut11" "D:/www/ut11/"
<Directory "D:/www/ut11/">
    AllowOverride All
    Options None
    Require all granted
    SetHandler 1c-application
    ManagedApplicationDescriptor "D:/www/ut11/default.vrd"
</Directory>

LoadModule _1cws_module — тот самый модуль расширения. Путь указывает на wsap24.dll внутри каталога bin вашей версии платформы; когда обновляете 1С — не забудьте поправить версию в пути, иначе публикация отвалится. SetHandler 1c-application включает обработчик 1С на этом пути, а ManagedApplicationDescriptor показывает, где лежит дескриптор базы.

Чтобы не собирать этот блок вручную каждый раз, я сделал конфигуратор: заполняете путь, папку базы и режим — получаете готовый блок для httpd.conf и заготовку default.vrd.

Публикация 1С на Apache через командную строку: утилита webinst

Конфигуратор — не единственный способ опубликовать базу. Вместе с платформой в каталоге bin ставится консольная утилита webinst, которая делает ровно то же самое: создаёт default.vrd и дописывает блок публикации в конфиг веб-сервера — но без единого клика мышью. Это то, что нужно для автоматизации: развернуть публикацию скриптом при выкатке, поднять её в CI или на Linux-сервере, где Конфигуратора с графикой попросту нет.

Базовый вызов для файловой базы на Apache 2.4 под Windows выглядит так:

"C:/Program Files/1cv8/8.3.27.1989/bin/webinst.exe" -publish -apache24 ^
  -wsdir ut11 ^
  -dir "D:/www/ut11" ^
  -connstr "File=""D:/bases/ut11"";" ^
  -confPath "D:/Server/Bin/Apache24/conf/httpd.conf"

Разбор ключей: -publish — публикуем (для снятия публикации есть -delete с теми же -wsdir и -confPath); -apache24 — тип веб-сервера (ещё бывают -apache22 и -iis); -wsdir — имя публикации, тот самый алиас из URL (/ut11); -dir — физическая папка публикации, куда ляжет default.vrd; -connstr — строка подключения к базе; -confPath — путь к httpd.conf, в который webinst допишет Alias и <Directory>. Для серверной (не файловой) базы меняется только строка подключения: -connstr "Srvr=""server1c"";Ref=""ut11"";".

На Linux та же команда, только пути другие, а webinst лежит в каталоге платформы:

/opt/1cv8/x86_64/8.3.27.1989/webinst -publish -apache24 \
  -wsdir ut11 \
  -dir /var/www/ut11 \
  -connstr 'Srvr="server1c";Ref="ut11";' \
  -confPath /etc/apache2/apache2.conf

После отработки утилиты остаётся перезапустить Apache — и база опубликована. Именно webinst выручает в связке с Docker, о которой я пишу ниже: там Конфигуратор упирается в «веб-серверы не обнаружены», а консольной публикации это безразлично — она просто пишет файлы, которые вы затем скармливаете контейнеру.

Частые ошибки при установке и публикации

Шесть ситуаций, на которые уходит больше всего времени у тех, кто публикует базу впервые.

  • Apache не стартует после правки httpd.conf. В подавляющем большинстве случаев — опечатка в пути или незакрытая директива. Гоняем httpd.exe -t (Windows) или apachectl configtest (Linux): команда покажет строку с ошибкой, вычитывать весь файл руками не нужно.
  • «Cannot load … wsap24.dll into server» при старте. Не совпадает разрядность: Apache x64 не загрузит 32-битный модуль и наоборот. Сверьте разрядность сборки Apache и установленной платформы 1С.
  • Модуль загрузился, но публикация отдаёт 404. Либо блок публикации попал в конфиг выше строки LoadModule _1cws_module, либо Alias не совпадает с тем, что вы запрашиваете в браузере. Проверьте секцию, которую дописал Конфигуратор или webinst.
  • «Ошибка при выполнении файловой операции» или «Недостаточно прав». Учётной записи, под которой работает служба Apache, не хватает прав на каталог файловой базы (или на порт менеджера кластера в клиент-серверном варианте). На Linux это обычно chown на каталог базы в пользу пользователя веб-сервера.
  • После обновления платформы публикация отвалилась. В LoadModule остался путь к bin старой версии — при обновлении 1С номер версии в пути меняется. Правится вручную, затем перезапуск Apache. Это же касается модуля wsisapi.dll на IIS.
  • Служба не появилась после httpd.exe -k install. Команда запущена не от администратора, либо служба Apache2.4 уже существует, но с другим путём: сначала httpd.exe -k uninstall, потом install из нужного каталога.

Отдельно про модуль: он версионируется под ветку веб-сервера — wsap22 для Apache 2.2, wsap24 для 2.4. Брать его нужно из того же дистрибутива платформы, что стоит на сервере 1С.

Несколько баз на одном Apache

Одно из главных преимуществ Apache для 1С — на одном веб-сервере спокойно живёт хоть десяток баз. Каждая база — это просто ещё одна пара Alias + <Directory>:

Alias "/ut11" "D:/www/ut11/"
<Directory "D:/www/ut11/">
    Require all granted
    SetHandler 1c-application
    ManagedApplicationDescriptor "D:/www/ut11/default.vrd"
</Directory>

Alias "/rz23" "D:/www/rz23/"
<Directory "D:/www/rz23/">
    Require all granted
    SetHandler 1c-application
    ManagedApplicationDescriptor "D:/www/rz23/default.vrd"
</Directory>

Управленческая база на /ut11, розница на /rz23, тестовая на /test — и всё это на одном порту, одним LoadModule. У меня на боевом Apache так опубликованы и рабочие базы, и отдельные публикации под интеграции.

Нюанс 1: зашиваем логин прямо в конфиг Apache

Вот приём, которого нет в стандартных инструкциях, а он экономит кучу времени на интеграциях. Когда к базе 1С ходит внешний сервис (вебхук, MCP-сервер, скрипт на Python), ему нужно проходить аутентификацию. Обычно креды передаёт клиент. Но можно зашить их прямо в конфиг Apache, и тогда клиенту вообще не надо ничего знать про пароль:

Alias "/ut11_mcp" "D:/www/ut11/"
<Directory "D:/www/ut11/">
    Require all granted
    # Apache сам подставит заголовок Basic-авторизации в каждый запрос
    RequestHeader set Authorization "Basic bWNwOjE="
    SetHandler 1c-application
    ManagedApplicationDescriptor "D:/www/ut11/default.vrd"
</Directory>

bWNwOjE= — это base64 от строки mcp:1 (логин mcp, пароль 1). Директива RequestHeader set Authorization добавляет заголовок Basic-авторизации в каждый входящий запрос ещё до того, как он попадёт в 1С. В итоге получается отдельная «служебная» публикация той же базы: обычные пользователи ходят на /ut11 и вводят пароль, а интеграция ходит на /ut11_mcp и авторизуется автоматически. Ровно так я публикую базу под MCP-сервер для 1С — клиенту не надо хранить пароль, он просто дёргает URL.

Модуль mod_headers для этого должен быть включён (LoadModule headers_module modules/mod_headers.so).

Нюанс 2: обходим CORS для HTTP-сервисов 1С

Если вы публикуете HTTP-сервисы 1С и дёргаете их из браузера (с фронтенда на другом домене), вы упрётесь в CORS. Браузер сначала шлёт preflight-запрос OPTIONS, и вот тут засада: обработчик 1С на OPTIONS толком не отвечает, и preflight падает. Лечится это так:

Alias "/ordermonitor" "D:/www/ordermonitor/"
<Directory "D:/www/ordermonitor/">
    Require all granted

    Header set Access-Control-Allow-Origin "*"
    Header always set Access-Control-Allow-Headers "*"
    Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"

    # Ключевой трюк: preflight OPTIONS отвечает сам Apache,
    # а всё остальное передаём обработчику 1С.
    <If "%{REQUEST_METHOD} != 'OPTIONS'">
        SetHandler 1c-application
        ManagedApplicationDescriptor "D:/www/ordermonitor/default.vrd"
    </If>
</Directory>

Идея в том, что CORS-заголовки Apache отдаёт всегда (через mod_headers), а обработчик 1С включается только для «настоящих» методов — GET, POST и так далее. На preflight OPTIONS Apache отвечает сам: пустой ответ 200 с нужными заголовками, и браузер спокойно шлёт основной запрос. Без этого <If> любой кросс-доменный вызов HTTP-сервиса из браузера будет отваливаться, и вы потратите вечер, гадая, почему «на бэкенде всё работает, а из фронта нет». Этот же приём выручает, когда 1С отдаёт данные во внешний сервис — например, в микросервис на FastAPI.

Access-Control-Allow-Origin "*" я тут ставлю для наглядности — в проде подставьте конкретный домен фронтенда, а не звёздочку.

Настройка HTTPS (SSL) для 1С в Apache

Как только вы начинаете гонять через веб-сервер что-то серьёзнее теста — обмен с магазином, оплату, персональные данные, — соединение нужно шифровать. Я в своё время наступил на это ровно с интернет-магазином: часть запросов не работала именно потому, что соединение было незащищённым, а после настройки SSL всё поднялось.

Для локальной разработки хватит самоподписанного сертификата. Генерируем ключ и сертификат утилитой OpenSSL (она лежит в bin Apache):

openssl genrsa -out localhost.key 2048
openssl req -new -key localhost.key -out localhost.csr
openssl x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt

При генерации в поле Common Name укажите ровно то имя, по которому будете открывать сайт (localhost или ваш домен) — иначе браузер будет ругаться на несоответствие. Дальше подключаем mod_ssl, слушаем 443-й порт и указываем сертификаты:

LoadModule ssl_module modules/mod_ssl.so
Listen 443

<VirtualHost _default_:443>
    DocumentRoot "D:/www"
    ServerName localhost:443
    SSLEngine on
    SSLCertificateFile    "D:/Server/Bin/Apache24/cert/localhost.crt"
    SSLCertificateKeyFile "D:/Server/Bin/Apache24/cert/localhost.key"
</VirtualHost>

Самоподписанному сертификату браузер по умолчанию не доверяет — чтобы убрать предупреждение, добавьте localhost.crt в «Доверенные корневые центры сертификации» локального компьютера. Для боевого сервера самоподписанный не годится: берите бесплатный сертификат Let's Encrypt или платный у регистратора (reg.ru и подобные часто дают год SSL в подарок к домену). Принцип подключения тот же — меняются только файлы сертификата и цепочки.

Нюанс, из-за которого openssl не запускается

Утилита openssl.exe лежит в каталоге bin Apache, но без переменной OPENSSL_CONF она падает с жалобой на конфигурацию. Поэтому команды выполняются так:

cd C:\Server\Bin\Apache24\bin
set OPENSSL_CONF=C:\Server\Bin\Apache24\conf\openssl.cnf

openssl.exe genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out localhost.key
openssl.exe req -new -key localhost.key -out localhost.csr
openssl.exe x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt

Командная строка Windows: генерация ключа и запроса на сертификат утилитой openssl.exe для localhost

Сертификат и ключ удобно сложить в отдельную папку certs в корне веб-сервера, а не держать в bin вперемешку с бинарниками.

Папка certs на диске C: с перенесёнными сертификатом и ключом localhost

Почему браузер ругается и как это убрать

Самоподписанному сертификату браузер не доверяет по определению — цепочку доверия строить не от кого.

Chrome: предупреждение «Подключение к сайту не защищено», самоподписанный сертификат недействителен

Лечится добавлением localhost.crt в «Доверенные корневые центры сертификации» локального компьютера (не текущего пользователя — иначе служба и тонкий клиент его не увидят).

Окно «Выбор хранилища сертификата»: пункт «Доверенные корневые центры сертификации»

Действующий сертификат: хостер или Let's Encrypt

Для боевого сервера самоподписанный не годится. Два рабочих пути.

Сертификат от хостера. При покупке домена многие регистраторы дают бесплатный SSL на год — заказывается в личном кабинете, подтверждение владения доменом идёт через TXT-запись в DNS. В ответ приходит письмо с телом сертификата и ключом: их кладут обычными текстовыми файлами рядом с localhost.crt и прописывают в конфиге.

Письмо от REG.RU с TXT-записью _globalsign-domain-verification для подтверждения домена

Пока сайт разрабатывается локально, домен нужно увести на свою машину через файл hosts — иначе запросы уйдут в интернет, а не на локальный Apache:

127.0.0.1    www.web1s.site

Let's Encrypt через certbot — если Apache стоит на Linux, это проще и дешевле. Certbot ставится пакетом, сам находит нужный <VirtualHost> и прописывает в него SSLCertificateFile и SSLCertificateKeyFile. Сертификат живёт 90 дней, но certbot ставит systemd-таймер, который проверяет срок пару раз в сутки и продлевает автоматически — в отличие от годового сертификата от хостера, который придётся продлевать руками.

Логика в обоих случаях одна: получить пару «сертификат + приватный ключ», указать пути в директивах внутри <VirtualHost *:443>, перезапустить Apache. Отличается только выпускающий центр и частота обновления.

Несколько сайтов на 443: виртуальные хосты

Когда на одном Apache живёт больше одного домена, конфигурацию удобнее вынести в conf/extra/httpd-vhosts.conf (подключается раскомментированной строкой Include в конце httpd.conf). У каждого блока — свой ServerName и свои сертификаты.

httpd-vhosts.conf: VirtualHost *:443 с DocumentRoot, ServerName и путями к сертификату web1s.site

Готовый результат выглядит так: замок в адресной строке, цепочка доверия выстроена до корневого центра.

Окно «Сертификат», вкладка «Путь сертификации»: цепочка GlobalSign Root CA — GlobalSign RSA DV SSL CA 2018 — www.web1s.site

Чек-лист: HTTPS не поднимается

Если после настройки соединение не устанавливается, браузер ругается на сертификат или тонкий клиент не достукивается до базы — проверяйте по порядку.

  • mod_ssl не подключён. Строка LoadModule ssl_module modules/mod_ssl.so должна быть раскомментирована. Без неё Apache просто не распознаёт директивы SSLEngine и SSLCertificateFile.
  • Порт 443 занят. На Windows его часто держит уже установленный IIS. Проверка: netstat -aon | findstr :443.
  • Сертификат просрочен или выписан не на тот домен. И браузер, и тонкий клиент сверяют срок действия и совпадение Common Name/SAN с адресом. Сертификат для localhost не подойдёт для внешнего домена.
  • Права на приватный ключ. На Linux файл .key должен быть читаем только пользователем Apache, права 600. Слишком открытые права — типичная причина отказа стартовать при строгих политиках.
  • Неполная цепочка сертификатов. Если сертификат выдан центром с промежуточным звеном, нужен SSLCertificateChainFile (или единый файл с полной цепочкой для Apache 2.4.8+). Без него часть клиентов не построит цепочку доверия.
  • Несколько <VirtualHost> на 443 без ServerName. Apache не сможет по SNI определить, какой сертификат отдавать.
  • Тонкий клиент не доверяет сертификату. Ошибка «удалённый узел не прошёл проверку» — сертификат не добавлен в доверенные на стороне клиента. Для самоподписанного это делается вручную, для Let's Encrypt и сертификата хостера не требуется.
  • Конфиг поправлен, но Apache не перезапущен. Или перезапущен с опечаткой — httpd.exe -t перед каждым рестартом.

Публикация 1С на веб-сервере IIS

Если у вас Windows Server и не хочется ставить сторонний веб-сервер, публикуйте на встроенном IIS. Порядок такой:

  1. Диспетчер серверов → Добавить роли и компоненты → Веб-сервер (IIS). В компонентах разработки приложений обязательно отметьте ISAPI Extensions и ISAPI Filters — без них 1С работать не будет.
  2. Установите платформу 1С с галочкой «Модули расширения веб-сервера».
  3. В Конфигураторе: Администрирование → Публикация на веб-сервере, выбираете IIS, жмёте «Опубликовать».

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

  • Нет доступа к папке базы. Первая же публикация упирается в права: пользователю, под которым работает IIS (группа IIS_IUSRS), нужно дать полный доступ к папке файловой базы. Свойства папки → Безопасность → добавить IIS_IUSRS → Полный доступ.
  • Пустая страница или ошибка модуля. Не доустановлены компоненты ISAPI/ASP — вернитесь в мастер ролей и доставьте их (при извлечённом установочном диске укажите альтернативный путь к sources\sxs).
  • HTTP 403.14. Веб-сервер настроен не отдавать листинг каталога. В пуле приложения переключите Managed Pipeline Mode на Classic.
  • 32-разрядная 1С на 64-битном сервере. В дополнительных параметрах пула поставьте «Разрешены 32-разрядные приложения» → True.
  • База не открывается после обновления платформы. Проверьте Сопоставления обработчиков (Handler Mappings): обработчик 1C Web Server Extension должен указывать на wsisapi.dll текущей версии платформы. После обновления 1С путь надо поправить.

После всех настроек перезапустите сайт в диспетчере IIS и откройте http://localhost/имя_базы — должен запуститься веб-клиент.

Пошаговую установку самого IIS на Windows Server 2019 под 1С (роли, веб-компонента платформы) я вынес в отдельный разбор «Установка IIS на Windows Server 2019 для 1С».

Бонус: Apache в Docker, 1С на хосте — и почему это спорная затея

Соблазнительный сценарий — вынести Apache в Docker-контейнер, а саму 1С оставить на хостовой машине. Веб-сервер изолирован, переносится одной командой и не мусорит в системе. Я довёл эту связку до реально открывающегося веб-клиента УТ и покажу все конфиги: что где лежит и почему. Но сразу честно предупрежу — по итогам граблей: для файловой базы этот подход сомнителен, и ниже объясню, во что он упирается.

Грабля №1: Конфигуратор не видит веб-сервер в контейнере

Первое, обо что спотыкаешься: пытаешься опубликовать базу через диалог «Публикация на веб-сервере», а Конфигуратор пишет «веб-серверы не обнаружены». И это не баг. Диалог ищет локально установленный веб-сервер: Apache — по записям в реестре и службах Windows, IIS — по установке в системе. Apache внутри Docker для Конфигуратора — «другая машина», он его не найдёт в принципе. Да и нашёл бы — сгенерировал бы конфиг с Windows-путями (wsap24.dll, D:\...), а контейнеру нужны Linux-пути.

Вывод: в связке с Docker диалог Конфигуратора не применяется. Публикацию собираем вручную — а это ровно те два артефакта, что генерирует диалог: файл default.vrd в папке публикации и блок в конфиге Apache.

Грабля №2: одного wsap24.so недостаточно

Внутри контейнера Apache работает на Linux, поэтому ему нужен модуль wsap24.so из дистрибутива 1С для Linux, а не wsap24.dll. Но просто скопировать один файл не выйдет — я на этом обжёгся дважды:

  1. При загрузке wsap24.so тянет за собой ядро платформы: core83.so, nuke83.so, библиотеки ICU, libunwind. Без них Apache падает на старте с core83.so: cannot open shared object file.
  2. При работе с базой платформа догружает компоненты в рантайме (xml2.so и десятки других). Отдашь только ядро — получишь Error loading component xml2 уже в браузере.

Практический вывод: в контейнер надо отдавать весь каталог платформы 1С для Linux (~2 ГБ), а не отдельные файлы. Достать его можно, не устанавливая 1С на машину, — headless-распаковкой дистрибутива во временном контейнере:

# setup-full-*.run — установщик 1С для Linux (ELF, не архив), внутри компонент ws = веб-расширение
docker run --rm \
  -v "/путь/к/дистрибутиву:/dist:ro" \
  -v "/путь/к/проекту/1c-platform:/out" \
  debian:bookworm-slim bash -c '
    cp /dist/setup-full-*.run /tmp/s.run && chmod +x /tmp/s.run
    /tmp/s.run --mode unattended --unattendedmodeui none --enable-components ws
    cp -a /opt/1cv8/x86_64/*/. /out/   # весь каталог платформы на хост
  '

Версия платформы в контейнере обязана совпадать с версией на хосте.

Что где лежит: структура и конфиги

docker-apache-1c/
├── docker-compose.yml
├── Dockerfile
├── conf/
│   └── 1c-publications.conf      # блоки <Directory> публикаций (аналог того, что пишет Конфигуратор)
├── www/
│   └── ut/
│       └── default.vrd           # дескриптор публикации базы «ut»
└── 1c-platform/                  # ~2 ГБ: wsap24.so + все runtime-компоненты платформы 1С для Linux

docker-compose.yml — монтируем папку публикаций, конфиг, файлы базы и каталог платформы:

services:
  apache-1c:
    build: .
    container_name: apache-1c
    ports:
      - "8090:80"
    volumes:
      # Папка публикаций: сюда кладём default.vrd (для файловой базы Apache её и отдаёт)
      - ./www:/usr/local/apache2/htdocs/1c
      # Блоки публикаций (Alias + <Directory> с обработчиком 1c-application)
      - ./conf/1c-publications.conf:/usr/local/apache2/conf/extra/1c-publications.conf
      # Файлы файловой базы с хоста: модуль 1С открывает 1Cv8.1CD напрямую по этому пути
      - "D:/1S/Avito/UT11_4:/var/1c-bases/ut"
      # Каталог платформы 1С для Linux: wsap24.so + все компоненты, что грузятся в рантайме
      - "./1c-platform:/opt/1c:ro"
    extra_hosts:
      # Понадобится для клиент-серверной базы: так контейнер видит сервер 1С на хосте
      - "host.docker.internal:host-gateway"
    restart: unless-stopped

Dockerfile берёт официальный образ Apache, включает нужные модули и подключает модуль 1С из смонтированного каталога платформы. LD_LIBRARY_PATH обязателен — иначе загрузчик не найдёт core83.so рядом с wsap24.so:

FROM httpd:2.4

# Каталог платформы 1С монтируется в /opt/1c (volume в docker-compose.yml).
# LD_LIBRARY_PATH нужен, чтобы загрузчик находил core83.so и прочие библиотеки 1С.
ENV LD_LIBRARY_PATH=/opt/1c

RUN set -eux; \
    sed -i \
      -e 's|^#\(LoadModule rewrite_module\)|\1|' \
      -e 's|^#\(LoadModule headers_module\)|\1|' \
      /usr/local/apache2/conf/httpd.conf; \
    printf '\nLoadModule _1cws_module /opt/1c/wsap24.so\nInclude conf/extra/1c-publications.conf\n' \
      >> /usr/local/apache2/conf/httpd.conf

EXPOSE 80

conf/1c-publications.conf — блок публикации. Это то, что Конфигуратор вписал бы сам, но с Linux-путями внутри контейнера:

Alias "/ut" "/usr/local/apache2/htdocs/1c/ut/"
<Directory "/usr/local/apache2/htdocs/1c/ut/">
    AllowOverride All
    Options None
    Require all granted
    SetHandler 1c-application
    ManagedApplicationDescriptor "/usr/local/apache2/htdocs/1c/ut/default.vrd"
</Directory>

И сам дескриптор www/ut/default.vrd. Для файловой базы в нём строка File= с путём внутри контейнера (тем, что смонтировали в docker-compose.yml):

<?xml version="1.0" encoding="UTF-8"?>
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
       base="/ut"
       ib="File=&quot;/var/1c-bases/ut&quot;;">
</point>

После docker compose up -d --build модуль загружается (httpd -M показывает _1cws_module), а по адресу http://localhost:8090/ut/ контейнерный Apache открывает базу и отдаёт стартовую страницу веб-клиента 1С. До этого места я связку довёл вживую.

Грабля №3, из-за которой всё это спорно: лицензия

А вот дальше веб-клиент упирается в стену: «Не найдена лицензия. Не обнаружен ключ защиты программы...». И это принципиальная проблема, а не недонастройка. При файловой базе платформенный код 1С исполняется внутри процесса Apache в контейнере, и лицензия нужна именно ему. А в контейнере (Linux в WSL2) недоступен ни один источник:

  • Аппаратный USB-ключ HASP — прокинуть USB в Docker Desktop на Windows практически нереально.
  • Программная лицензия — привязана к «железу»; активированная на Windows-хосте для контейнера недействительна, а сам контейнер эфемерный (пересоздал — параметры оборудования сменились, лицензия слетела).
  • Сетевой менеджер лицензий — работает, но его надо где-то поднять и прописать контейнеру nethasp.ini с адресом (например host.docker.internal).

Моя честная оценка

Разложить контейнерный Apache и открыть базу — получилось, и как разбор «что у публикации под капотом» это полезно. Но как боевое решение для файловой базы контейнерный Apache сомнителен: ты и так тащишь в контейнер 2 ГБ платформы, и всё равно упираешься в лицензирование, которое чисто в файловом варианте не решается без плясок.

Если действительно нужен Apache в Docker, разумны два пути:

  1. Клиент-серверная база. Сервер 1С (лицензированный своим ключом) живёт на хосте или в отдельном контейнере, а default.vrd указывает не на файл, а на сервер: ib="Srvr=&quot;host.docker.internal:1541&quot;;Ref=&quot;имя_базы&quot;;". Тогда лицензию сеансу выдаёт сервер, и проблема контейнера снимается. Это правильный production-путь.
  2. Полноценное сетевое лицензирование — поднять менеджер лицензий и настроить nethasp.ini. Оправдано, если такая инфраструктура уже есть.

Файловую базу для веб-доступа в любом случае стоит перевести в клиент-серверную: и по лицензиям, и по производительности (файловый 1Cv8.1CD через bind-mount заметно медленнее нативного, плюс конфликты одновременного доступа с толстым клиентом).

Публикация 1С за реверс-прокси NGinx

Ещё один рабочий сценарий: перед Apache или IIS (либо прямо перед опубликованным HTTP-сервисом 1С) ставят NGinx как реверс-прокси. Он берёт на себя TLS-терминацию, ограничение доступа (allow/deny по IP, Basic Auth), лимиты запросов и балансировку — а сам HTTP-сервис 1С остаётся «прозрачным» и про то, что перед ним стоит прокси, ничего не знает. Весь контроль доступа выносится наружу, из BSL-кода.

Со стороны 1С публикуется обычный HTTP-сервис без встроенной в код аутентификации. Например, отдача номенклатуры в JSON (корень сервиса — nci):

Функция ProductGET(Запрос)
    Ответ = Новый HTTPСервисОтвет(200);
    ДанныеНоменклатуры = Новый Массив;

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка КАК Ссылка,
    |   Номенклатура.Наименование КАК Наименование
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура";
    Выборка = Запрос.Выполнить().Выбрать();

    Пока Выборка.Следующий() Цикл
        Данные = Новый Структура;
        Данные.Вставить("uuid", XMLСтрока(Выборка.Ссылка));
        Данные.Вставить("name", Выборка.Наименование);
        ДанныеНоменклатуры.Добавить(Данные);
    КонецЦикла;

    Ответ.УстановитьТелоИзСтроки(СформироватьJSON(ДанныеНоменклатуры),
        КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    Возврат Ответ;
КонецФункции

В коде обработчика нет ни проверки логина, ни разбора заголовков X-Forwarded-For — доступ ограничивается двумя вещами снаружи: отдельной ролью веб-пользователя (минимум прав — чтение одного справочника и вызов одного метода) и настройками самого NGinx. Конфигурация прокси лежит уже вне 1С, в nginx.conf; ключевое здесь — чтобы сегмент пути публикации (nci) совпадал в location и в адресе опубликованного .1cws:

server {
    listen 443 ssl;
    server_name api.example.ru;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    location /nci/ {
        # TLS и контроль доступа — здесь, а не в BSL
        auth_basic           "1C API";
        auth_basic_user_file /etc/nginx/.htpasswd;

        proxy_pass http://127.0.0.1:8080/base_nci/hs/nci/;
        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;
    }
}

Такой слой удобно накрутить поверх уже настроенной публикации Apache/IIS из разделов выше: 1С отдаёт голый HTTP-сервис на localhost, а NGinx закрывает его сертификатом и Basic Auth наружу. Разбор REST-сервисов 1С и их интеграции с внешним бэкендом — на курсе интеграции (ссылка в конце статьи).

Итог

Публикация 1С на веб-сервере — навык, который открывает всю интеграционную часть платформы. Разберём кратко, что мы прошли: установили Apache 2.4 нужной разрядности, опубликовали базу и через Конфигуратор, и вручную через httpd.conf, разложили несколько баз на одном сервере, зашили логин прямо в конфиг для интеграций, обошли CORS для HTTP-сервисов, настроили HTTPS и разобрали публикацию на IIS со всеми типовыми ошибками. А в бонусе честно прошли путь с Apache в Docker — до открытой базы в браузере и до понимания, где этот путь упирается в лицензирование и почему для файловой базы он спорный.

Если хотите не просто повторить шаги, а системно разобраться в интеграции 1С с внешним миром — HTTP-сервисы, OData, обмен с сайтами и внешними сервисами, — это ровно то, чему я учу в курсе по интеграции 1С. Публикация на веб-сервере там первый шаг, с которого начинается всё остальное.

А начать можно с занятия по HTTP-сервисам в 1С: опубликовали базу — и сразу отдаёте и принимаете данные по HTTP.

Частые вопросы