Меня зовут Евгений Семёнов, я технический директор компании «АйТи Фреш». Пятнадцать с лишним лет мы обслуживаем московские офисы до 50 рабочих мест и держим собственные серверы в дата-центре МТС. В обзорной статье серии я рассказывал, что такое GLPI и почему мы ставим его клиентам вместо платных хелпдесков. Сегодня — чистая практика: наш внутренний регламент, по которому инженер «АйТи Фреш» превращает голый VPS в работающий портал заявок за один вечер. Все команды ниже — боевые, с реальных внедрений; их можно повторять построчно. Ставим актуальную на июль 2026 года версию GLPI 11.0.8 — и сразу предупреждаю: одиннадцатая ветка ставится не так, как десятая, и большинство русскоязычных мануалов, которые гуглятся первыми, на ней молча ломаются. Где именно — покажу по ходу.
Выбор площадки и размер сервера
Начнём с вопроса, который заказчик задаёт первым: «Сколько это будет стоить по железу?» Ответ приятный: почти нисколько. GLPI — классическое PHP-приложение с базой MariaDB, и на офис до 50 рабочих мест ему хватает самого скромного VPS. Наша проверенная норма — 2 vCPU, 4 ГБ оперативной памяти, 40 ГБ SSD. У российских хостеров такая конфигурация стоит порядка 600–900 ₽ в месяц — дешевле одной лицензии любого облачного хелпдеска на одного агента. По факту GLPI с полусотней подключённых агентов инвентаризации у нас ест меньше 2 ГБ памяти; остальное — запас под пики, базу и файловый кеш.
| Параметр | Минимум (до 50 РМ) | С запасом (рост, плагины) |
|---|---|---|
| vCPU | 2 ядра | 4 ядра |
| RAM | 4 ГБ | 8 ГБ |
| Диск | 40 ГБ SSD | 80 ГБ SSD (вложения к заявкам растут) |
| ОС | Ubuntu Server 24.04 LTS | та же, минимальная установка |
| Цена у РФ-хостеров | ~600–900 ₽/мес | ~1200–1800 ₽/мес |
Когда VPS — не вариант? Два честных случая из нашей практики. Первый: у офиса нет белого IP и служба безопасности категорически против того, чтобы список компьютеров, пользователей и заявок жил вне периметра. Тогда ставим ту же связку на локальный гипервизор — Hyper-V или Proxmox, виртуалка с теми же 2 vCPU / 4 ГБ. Второй: филиалы должны работать с порталом даже при упавшем интернет-канале в главном офисе — тогда наоборот, VPS выигрывает, потому что доступен отовсюду. Всё, что написано ниже, одинаково работает и на VPS, и на локальной виртуалке; разница только в том, что на локальной инсталляции вместо Let's Encrypt придётся выпускать сертификат на внутреннем CA или довольствоваться самоподписанным.
Совет из практики: берите VPS в российской юрисдикции. Портал заявок хранит ФИО, телефоны и почту сотрудников — это персональные данные, и по 152-ФЗ им положено лежать на территории РФ. Заодно не будет проблем с доступностью, когда очередной зарубежный хостер закроет оплату из России.
Подготовка стека: Ubuntu 24.04, PHP 8.3, MariaDB 10.11, nginx
GLPI 11 требует PHP не ниже 8.2 и MariaDB не ниже 10.6 (или MySQL 8.0). Прелесть Ubuntu 24.04 LTS в том, что штатные репозитории закрывают оба требования без единого стороннего PPA: из коробки едут PHP 8.3 и MariaDB 10.11. Никаких «подключите ondrej/php», как в мануалах времён Ubuntu 20.04, — ставим всё родное, обновления безопасности будут прилетать штатно до 2029 года. Итоговый стек выглядит так: снизу Ubuntu, над ней MariaDB и PHP-FPM, сверху nginx, раздающий GLPI в браузер пользователя.
PHP 8.3 и обязательные модули
Начинаем с обновления системы, часового пояса и установки PHP-FPM со всеми расширениями, которые GLPI 11 объявляет обязательными. Обратите внимание на php8.3-ldap — без него не будет подключения к Active Directory, и на то, что в одиннадцатой ветке в списке обязательных появился openssl: он нужен для защищённого обмена с агентами инвентаризации и для OAuth 2.0. В Ubuntu он вкомпилирован в PHP по умолчанию, но проверить на экране требований мастера всё равно стоит.
sudo apt update && sudo apt upgrade -y
sudo timedatectl set-timezone Europe/Moscow
sudo apt install -y nginx mariadb-server \
php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd php8.3-intl \
php8.3-xml php8.3-mbstring php8.3-zip php8.3-bz2 php8.3-ldap
php -v # PHP 8.3.x — подходит (требование GLPI 11: PHP 8.2+)
mariadb --version # 10.11.x — подходит (требование: 10.6+)
Сразу поправим два лимита PHP, о которые пользователи спотыкаются в первый же день: размер загружаемых вложений (сканы и скриншоты к заявкам легко весят больше дефолтных 2 МБ) и таймзону:
sudo sed -i 's/^upload_max_filesize.*/upload_max_filesize = 32M/' /etc/php/8.3/fpm/php.ini
sudo sed -i 's/^post_max_size.*/post_max_size = 32M/' /etc/php/8.3/fpm/php.ini
sudo sed -i 's|^;date.timezone.*|date.timezone = Europe/Moscow|' /etc/php/8.3/fpm/php.ini
sudo systemctl restart php8.3-fpm
MariaDB: utf8mb4 и грабля с часовыми поясами
Базу готовим в три шага. Первый — базовая гигиена свежей MariaDB:
sudo mariadb-secure-installation
# root-пароль задаём, анонимных пользователей и тестовую базу сносим,
# удалённый root-вход запрещаем — на все вопросы отвечаем Y
Второй — создаём базу и отдельного пользователя. Кодировка строго utf8mb4: на устаревшей utf8 (трёхбайтовой) GLPI будет ругаться при установке, а эмодзи в тексте заявки — а их бухгалтеры вставляют чаще, чем вы думаете, — уронят запись в базу:
sudo mariadb
CREATE DATABASE glpi CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'glpi'@'localhost' IDENTIFIED BY 'СложныйПарольСюда';
GRANT ALL PRIVILEGES ON glpi.* TO 'glpi'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Третий шаг — классическая грабля, о которую спотыкаются буквально все, кто ставит GLPI впервые: таблицы часовых поясов. MariaDB из коробки про таймзоны ничего не знает, и мастер установки GLPI честно предупредит, что не может включить поддержку часовых поясов. Лечится двумя командами — загружаем зоны из системной базы zoneinfo и даём пользователю GLPI право их читать:
mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mariadb mysql
sudo mariadb -e "GRANT SELECT ON mysql.time_zone_name TO 'glpi'@'localhost'; FLUSH PRIVILEGES;"
Если пропустить второй GRANT, GLPI так и будет считать, что таймзон нет, — право на чтение mysql.time_zone_name обычным пользователям по умолчанию не выдаётся.
nginx против Apache и главная грабля GLPI 11: docroot теперь public/
GLPI одинаково живёт под Apache и nginx, но мы на внедрениях берём nginx + PHP-FPM: меньше памяти, проще конфиг, и тот же nginx потом терминирует TLS. А теперь главное отличие одиннадцатой ветки, из-за которого не работают почти все мануалы 2020–2022 годов: корнем веб-сервера обязан быть каталог public/ внутри GLPI, а не корень распакованного архива. В десятке такая схема была рекомендацией — можно было по старинке указать root /var/www/glpi, и всё работало. В GLPI 11 весь вход идёт через фронт-контроллер public/index.php, и если направить веб-сервер в корень, вы получите либо белый экран, либо, что хуже, наружу окажутся выставлены конфиги и файлы данных. Правильный server-block выглядит так:
sudo tee /etc/nginx/sites-available/glpi <<'EOF'
server {
listen 80;
server_name glpi.example.ru;
root /var/www/glpi/public;
index index.php;
client_max_body_size 32M;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/glpi /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
Заметьте: PHP-запросы разрешены только для index.php. Это не небрежность, а осознанная защита — исполнять произвольные PHP-файлы из веб-рута GLPI 11 не должен никто, вся маршрутизация идёт через фронт-контроллер.
Установка GLPI 11: архив, права, каталоги вне веб-рута, мастер
Дистрибутив забираем с GitHub-релизов проекта glpi-project/glpi — это единственный официальный канал. Распаковываем в /var/www:
cd /tmp
wget https://github.com/glpi-project/glpi/releases/download/11.0.8/glpi-11.0.8.tgz
tar -xzf glpi-11.0.8.tgz -C /var/www/
sudo chown -R www-data:www-data /var/www/glpi
Дальше шаг, который отличает аккуратную инсталляцию от «поставил и забыл»: выносим изменяемые данные — конфиги, вложения, логи, сессии — из веб-рута. GLPI поддерживает это штатно, через так называемую downstream-схему: создаём файл inc/downstream.php, который указывает, где лежит конфигурация, а уже в конфигурационном каталоге определяем каталоги данных и логов:
sudo mkdir -p /etc/glpi /var/lib/glpi /var/log/glpi
sudo tee /var/www/glpi/inc/downstream.php <<'EOF'
<?php
define('GLPI_CONFIG_DIR', '/etc/glpi/');
if (file_exists(GLPI_CONFIG_DIR . '/local_define.php')) {
require_once GLPI_CONFIG_DIR . '/local_define.php';
}
EOF
sudo tee /etc/glpi/local_define.php <<'EOF'
<?php
define('GLPI_VAR_DIR', '/var/lib/glpi');
define('GLPI_LOG_DIR', '/var/log/glpi');
EOF
sudo chown -R www-data:www-data /etc/glpi /var/lib/glpi /var/log/glpi
Зачем это нужно, если public/ и так прикрывает файлы от прямого скачивания? Затем, что при обновлении GLPI вы просто заменяете каталог с кодом, не трогая /etc/glpi и /var/lib/glpi, — данные и настройки живут своей жизнью. Плюс резервное копирование сводится к двум путям и дампу базы. Один раз потратив три минуты на downstream, вы экономите их на каждом апгрейде.
Теперь открываем http://glpi.example.ru в браузере — стартует мастер установки. Первым же экраном он предлагает выбрать язык: выбираем русский, весь дальнейший интерфейс будет локализован. Дальше по шагам: лицензия GPL, «Установить», проверка требований — вот здесь мастер сверяет версию PHP и наличие всех расширений, включая openssl и ldap; если на предыдущих шагах ничего не пропущено, весь список будет зелёным. Затем подключение к базе: сервер localhost, пользователь glpi, пароль из шага с MariaDB, выбираем созданную базу — и несколько минут ждём, пока зальётся схема. В финале мастер задаст пару вопросов про отправку анонимной статистики (мы выключаем) и покажет стартовые учётные записи.
Не пропустите: на последнем экране мастер напомнит удалить установочный скрипт. В 11-й ветке установочный каталог спрятан за фронт-контроллером, но оставлять инсталлятор доступным всё равно нельзя: rm /var/www/glpi/install/install.php — и только после этого пускаем на портал живых людей. GLPI будет показывать предупреждение в интерфейсе, пока файл на месте.
HTTPS сразу, а не потом
Здесь у меня жёсткое правило, выстраданное аудитами чужих инсталляций: портал заявок без TLS в прод не выпускаем. Через форму логина GLPI, подключённого к Active Directory, ходят доменные пароли бухгалтеров, юристов и директора. Отдавать их открытым HTTP через публичный интернет — значит подарить их первому же, кто окажется на пути пакета. Поэтому сертификат ставим до того, как сообщаем адрес портала пользователям, а не «потом как-нибудь».
С Let's Encrypt на nginx это три команды. Важная деталь — используем плагин --nginx, а не --standalone: standalone-режим поднимает собственный веб-сервер на 80-м порту, который занят нашим nginx, и первое же автопродление через три месяца молча провалится. Плагин nginx вместо этого сам подкладывает проверочный ответ в работающий сайт и сам же дописывает в server-block ssl-директивы и редирект с HTTP:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d glpi.example.ru --redirect -m admin@example.ru --agree-tos
# автопродление уже настроено пакетом — проверяем таймер и делаем прогон вхолостую
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
Финальный штрих — HSTS, чтобы браузеры сотрудников даже не пытались ходить по HTTP. В ssl-секцию server-блока добавляем:
add_header Strict-Transport-Security "max-age=31536000" always;
Из практики: на одном из аудитов мы нашли портал заявок, три года просивший пароли по чистому HTTP, — при том что сертификат Let's Encrypt бесплатен, а его настройка занимает меньше времени, чем чтение этого раздела. Худший вид экономии — экономия на трёх командах.
Подключаем Active Directory
Ручное заведение полусотни пользователей убивает саму идею хелпдеска: людям придётся помнить ещё один пароль, а вам — вечно синхронизировать кадровые изменения руками. Поэтому сразу подключаем GLPI к контроллеру домена: сотрудник входит в портал той же учёткой, что и в Windows, а карточки пользователей наполняются из AD автоматически.
Сервисная учётка и настройка коннектора
Первое и принципиальное: для чтения каталога GLPI нужна отдельная сервисная учётная запись с минимальными правами. Не администратор домена — никогда. Обычный доменный пользователь по умолчанию умеет читать каталог, этого достаточно; заведите в AD учётку вида svc-glpi с бессрочным паролем и запретом интерактивного входа. Если портал стоит на VPS, между ним и контроллером должен быть закрытый канал — мы пробрасываем site-to-site VPN или, минимум, открываем LDAP-порт на файрволе строго с IP виртуалки.
Сам коннектор живёт в Настройки → Аутентификация → Каталоги LDAP. Нажимаем «Добавить», выбираем предзаполненный шаблон Active Directory и заполняем:
- Сервер: IP или FQDN контроллера домена, порт 389 (про 636 — ниже);
- BaseDN: откуда читать каталог, например
OU=Staff,DC=corp,DC=example,DC=ru— сразу сужайте до OU с живыми сотрудниками, а не корень домена, иначе в GLPI приедут служебные и технические учётки; - rootdn / пароль: та самая сервисная учётка
svc-glpi@corp.example.ru; - Фильтр подключения: шаблон AD уже подставляет условие «пользователь и не отключён» —
(&(objectClass=user)(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))); при необходимости добавьте к нему членство в группе.
Кнопка «Проверить» должна ответить, что соединение установлено. Если нет — сначала проверьте сетевую доступность с самого VPS: ldapsearch -H ldap://dc01.corp.example.ru -D "svc-glpi@corp.example.ru" -W -b "DC=corp,DC=example,DC=ru" sAMAccountName покажет, в сети проблема или в реквизитах.
Маппинг полей: телефон, отдел, руководитель
На вкладке сопоставления полей не ограничивайтесь логином и почтой. Мы всегда маппим telephoneNumber → телефон, department → подразделение, title → должность и manager → руководитель. Кажется мелочью, но потом это работает на вас: инженер видит в заявке телефон и отдел заявителя, не переспрашивая, а поле «руководитель» пригодится, когда дорастёте до согласований — заявка «прошу выдать ноутбук» сама уйдёт на утверждение начальнику отдела.
Синхронизация по cron и судьба уволенных
Импорт пользователей запускается из Администрирование → Пользователи → Связь с каталогом LDAP — при первом проходе забираем всех из нужной OU. Дальше синхронизацию гоняет автоматика: внутренняя задача GLPI по расписанию сверяет каталог (о запуске планировщика — в чек-листе ниже). Отдельно решите, что происходит с уволенными: в Настройки → Аутентификация есть политика для пользователей, пропавших из каталога. Мы ставим «деактивировать» — учётка блокируется, но история её заявок остаётся в базе. Удалять нельзя: вместе с пользователем осиротеют его заявки, и статистика за год превратится в решето.
Грабля: LDAPS против 389-го порта
Свежие контроллеры домена всё чаще требуют подписи LDAP-канала (channel binding и LDAP signing — Microsoft закручивает эти гайки с 2020 года), и тогда простая связка по 389-му порту перестаёт проходить аутентификацию. Симптом характерный: «Проверить» в коннекторе проходит, а реальный вход пользователя — нет, либо в логах DC сыплются события 2889. Лечение — переходить на LDAPS, порт 636: в настройках коннектора включаем TLS, меняем порт, а на VPS кладём в доверенные корневой сертификат вашего внутреннего CA, которым подписан сертификат контроллера. Заодно и реквизиты сервисной учётки перестают летать по каналу в открытом виде — по-хорошему, LDAPS стоит включать не «когда заставят», а сразу.
Базовая настройка заявок: сущности, категории, SLA, почта
GLPI после установки — это конструктор с тысячей ручек, и главная ошибка новичка — начать крутить их все. Для одной организации до 50 рабочих мест наш рецепт короткий.
Сущности (entities) не плодим. Механизм entities создан для холдингов и MSP с десятками обособленных клиентов; для одной конторы вся работа живёт в корневой сущности. Каждая лишняя entity — это отдельные правила, отдельные права и отдельная путаница. Понадобится второе юрлицо — добавите за пять минут, когда оно реально появится.
Категорий заявок — пять-семь, не сорок. Пользователь, увидев выпадающий список из сорока пунктов, выбирает первый попавшийся, и вся ваша аналитика по категориям превращается в шум. Наш типовой набор: «Компьютер и оборудование», «1С и программы», «Почта», «Сеть и интернет», «Доступы и учётные записи», «Принтеры и сканеры», «Прочее». Этого хватает, чтобы понимать, куда уходит время инженеров, и не пугать бухгалтера терминами.
Матрица SLA. В Администрирование → Правила → SLA заводим времена реакции и решения по приоритетам. Для малого офиса на аутсорсинге у нас работает такая матрица:
| Приоритет | Пример | Реакция | Решение |
|---|---|---|---|
| Критический | стоит сервер 1С, лежит сеть офиса | 15 минут | 4 часа |
| Высокий | не работает РМ бухгалтера в отчётный период | 30 минут | 8 часов |
| Средний | не печатает принтер, глючит почта у одного | 2 часа | 1 рабочий день |
| Низкий | установить программу, выдать доступ | 4 часа | 3 рабочих дня |
GLPI сам раскрасит просроченные заявки и умеет эскалировать их по уровням — но заработает это только вместе с планировщиком из чек-листа.
Почтовые уведомления. В Настройки → Уведомления включаем e-mail и вводим параметры SMTP. Мы отправляем через свой почтовый релей с аутентификацией и TLS; можно указать и корпоративный почтовый сервер напрямую. Обязательно нажмите «Отправить тестовое письмо» — молчащие уведомления обнаруживаются обычно через неделю, вместе с обиженным пользователем, который «писал вам, а вы не ответили».
Назначение по умолчанию. Заводим группу исполнителей (у нас — «Инженеры ITfresh»), включаем в неё учётки инженеров и правилом назначаем её исполнителем всех новых заявок. Заявка без исполнителя — это заявка, которую не увидел никто; правило по умолчанию гарантирует, что таких не будет физически.
Первый пользовательский сценарий end-to-end
Критерий готовности портала — не зелёные галочки в настройках, а один живой сквозной прогон. Мы всегда завершаем внедрение таким тестом, и пока он не пройден, система не сдана:
- Вход. Берём реального пользователя — лучше всего бухгалтера, это самый честный тестировщик, — он открывает
https://glpi.example.ruи входит своей доменной учёткой. Ни регистрации, ни нового пароля: LDAP отработал. - Заявка. В упрощённом интерфейсе (self-service, GLPI включает его обычным пользователям сам) он создаёт заявку через форму: категория «Принтеры и сканеры», описание «не печатает договор». Форму можно оставить штатную, а можно собрать свою в конструкторе форм — в 11-й ветке он встроен в ядро, и это одна из главных причин ставить именно её.
- Уведомление. Инженеру из группы по умолчанию падает письмо о новой заявке со ссылкой. Заявка уже назначена на группу — правило сработало, SLA-таймер пошёл.
- Решение. Инженер отвечает в заявке, пользователь получает письмо с ответом, инженер закрывает заявку с решением.
- Обратная связь. Пользователю приходит предложение оценить работу — опрос удовлетворённости включается в настройках сущности. Оценка легла в статистику.
Если вся цепочка прошла без единого звонка «а как тут у вас», — портал готов. Если где-то споткнулись, вы только что бесплатно нашли то, обо что через неделю споткнулись бы все пятьдесят сотрудников разом.
Чек-лист после установки: cron, пароли, fail2ban
Финальный проход по мелочам, которые отличают рабочую систему от бомбы замедленного действия.
1. Планировщик. Половина магии GLPI — уведомления, эскалации SLA, LDAP-синхронизация, чистка мусора — исполняется фоновыми задачами. Из коробки они цепляются к заходам пользователей на страницы, и это работает отвратительно: нет визитов — нет уведомлений. В 11-й ветке штатный путь — системный cron, гоняющий задачи раз в минуту-две от имени пользователя веб-сервера:
sudo crontab -u www-data -e
# добавляем строку:
*/2 * * * * php /var/www/glpi/front/cron.php
После этого в Настройки → Автоматические действия переводим задачи в режим CLI — и уведомления начинают ходить сами, независимо от того, смотрит ли кто-то в портал. Разовые сервисные операции удобно гонять через php bin/console из каталога GLPI — тем же инструментом выполняются и апгрейды базы при обновлениях.
2. Пароли встроенных учёток. Мастер установки создаёт четыре локальные записи: glpi/glpi (суперадмин), post-only, tech и normal — с паролями, совпадающими с логинами и известными всему интернету. В девяти из десяти чужих инсталляций, которые мы брали на сопровождение, эти учётки так и стояли нетронутыми — при портале, торчащем в интернет. Суперадмину меняем пароль на длинный случайный, остальные три отключаем; GLPI, к его чести, сам показывает предупреждение, пока дефолтные пароли живы.
3. fail2ban на форму логина. Портал на VPS доступен из интернета, значит, его будут брутфорсить — не «если», а «когда». GLPI пишет неудачные входы в свой журнал, и на него легко натравить fail2ban: фильтр по строке неудачной аутентификации в /var/log/glpi/php-errors.log, три промаха — бан IP на файрволе. Плюс базовая гигиена самого VPS: вход по SSH только по ключам, файрвол с открытыми только 80/443/22.
4. Анонимный FAQ и лишние интерфейсы. Проверьте в настройках, что база знаний не доступна без входа: анонимный FAQ включается одной галочкой и иногда оказывается включён «из коробки шаблоном» — а туда со временем попадают инструкции с внутренними адресами и именами серверов.
5. Бэкап. Ежедневный mariadb-dump glpi плюс архив /etc/glpi и /var/lib/glpi — и копию обязательно наружу, не на тот же VPS. Благодаря downstream-схеме из третьего раздела это ровно два каталога и один дамп.
На этом «один вечер» закончен: у офиса есть портал заявок под HTTPS, вход по доменным учёткам, SLA и работающие уведомления. Следующий шаг — заставить GLPI самому узнать, какое железо и софт стоят на каждом рабочем месте: раскатываем GLPI Agent 1.18 на весь Windows-парк через групповые политики. Этому посвящена следующая статья серии про автоинвентаризацию через GPO, а начать знакомство с системой можно с обзора GLPI 11. Если же разворачивать некому или некогда — напишите нам: развернём по этому же регламенту и возьмём на сопровождение. Telegram @ITfresh_Boss, +7 903 729-62-41.
Оставить комментарий