Node-служба не может занять порт 80
Приложения на Node часто настраивают на порт 80 или 443. От непривилегированного пользователя это невозможно: нужна отдельная возможность процесса, сокет-активация или веб-сервер впереди.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Порт ниже 1024 у службы от обычного пользователя
Ядро разрешает такие порты только с нужной возможностью. Приложение получает отказ и завершается.
-
Правильнее поставить веб-сервер впереди
Приложение на порту выше 1024 за обратным прокси — стандартная схема: она даёт TLS, сжатие, статику и защиту.
-
Менеджер процессов запускается вместо службы
Средства вроде pm2 дублируют работу systemd: два менеджера процессов мешают друг другу и путают состояние.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Пользователь и возможности службы.
systemctl show myapp.service -p User -p AmbientCapabilitiesСообщение приложения об отказе.
journalctl -u myapp.service -n 20 --no-pager | grep -iE "EACCES|listen"Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Ядро разрешает такие порты только с нужной возможностью. Приложение получает отказ и завершается.
- Как проверить
-
Посмотрите порт и пользователя.
systemctl show myapp.service -p User -p AmbientCapabilities journalctl -u myapp.service -n 20 --no-pager | grep -i EACCES
- Как исправить
-
Дайте службе только возможность привязки к привилегированным портам, оставив обычного пользователя.
[Service] AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE
- Почему происходит
- Приложение на порту выше 1024 за обратным прокси — стандартная схема: она даёт TLS, сжатие, статику и защиту.
- Как проверить
-
Посмотрите, есть ли веб-сервер и куда он обращается.
sudo nginx -T 2>/dev/null | grep proxy_pass | head
- Как исправить
- Переведите приложение на порт выше 1024 и настройте обратный прокси. Это надёжнее выдачи возможностей.
- Почему происходит
- Средства вроде pm2 дублируют работу systemd: два менеджера процессов мешают друг другу и путают состояние.
- Как проверить
-
Посмотрите команду запуска.
systemctl cat myapp.service | grep ExecStart
- Как исправить
- Запускайте приложение напрямую через systemd: перезапуск, журнал и ограничения он берёт на себя.
Пример вывода
Приложение пытается занять порт 80 от обычного пользователя. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
myapp[4100]: Error: listen EACCES: permission denied 0.0.0.0:80
myapp[4100]: at Server.setupListenHandle
systemd[1]: myapp.service: Main process exited, code=exited, status=1/FAILURE
Связанные ошибки
- bind: Permission denied при привязке к порту Отказ при привязке к порту: обычно порт ниже 1024 у службы от непривилегированного пользователя. Как дать возможность CAP_NET_BIND_SERVICE.
- status=218/CAPABILITIES в systemd Код 218/CAPABILITIES: не удалось применить набор возможностей процесса из CapabilityBoundingSet= или AmbientCapabilities=.
- status=4/NOPERMISSION в systemd Код 4/NOPERMISSION: программа сообщила о недостатке прав. По соглашению LSB это «у пользователя недостаточно привилегий».
- Служба IPsec запускается, а туннели не поднимаются Процесс работает, соединений нет: закрыты служебные порты, не совпадают параметры или нет прав на ключи.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- AppArmor: apparmor="DENIED" в журнале ядра Профиль AppArmor запретил операцию: как прочитать запись, найти профиль и поправить его правильно.
- Automount: каталог монтируется не вовремя или отваливается Автомонтирование через .automount: как работает TimeoutIdleSec, почему ресурс отваливается и когда лучше обычный .mount.
- Broken pipe в журнале службы Запись в закрытый канал или соединение: клиент отключился, обработчик завершился, конвейер разорван.
Где встречается чаще всего
Источники
-
systemd.exec(5)
AmbientCapabilities= и возможность привязки к портам. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено приложением на Node с портом 80 при User=app.