Короткий ответ
Не крутите systemctl restart nginx, пока nginx -t не зелёный. Сначала синтаксис и пути к сертификатам, затем кто слушает 80/443 на 10.0.20.40. Частые причины: опечатка в server_name, include на удалённый файл, ssl_certificate указывает на пустой путь после сбоя certbot, Apache уже занял порт. Хост сайта — site.example, корень /var/www/site.example.
nginx -t читает конфиг от имени процесса; если тест проходит, а unit падает — смотрите journalctl -u nginx и ss -tlnp. Не удаляйте /etc/nginx «чтобы поставить заново».
Симптомы и как отличить
Типичная картина:
systemctl is-active nginx=failedилиinactive;- сайт не открывается,
curl -I http://10.0.20.40даёт connection refused; - в журнале
nginx.service: Failed with result 'exit-code'.
Отличия:
| Что видно | Это не «nginx лёг» | Куда |
|---|---|---|
| Unit active, сайт 502 | upstream мёртв | 502 Bad Gateway |
| Unit active, 403 | root/права | 403 Forbidden |
| Apache слушает 80, nginx failed bind | конфликт пакетов | Apache не запускается |
cannot load certificate | TLS-файлы | Let's Encrypt |
Возможные причины
От частых к редким:
- Синтаксическая ошибка в
/etc/nginx/sites-enabled/после ручной правки. listen 80илиlisten 443 ssl— порт уже занят Apache, другим nginx, Docker или NPM.ssl_certificate/ssl_certificate_keyуказывают на несуществующий файл (certbot не выпустил, live-каталог пуст).- Права: ключ
privkey.pemнедоступен пользователюwww-data/nginxиз‑за слишком закрытого каталога — реже, обычно читает root при старте. - Дублирующий
default_serverи конфликтserver_name. - Модуль в
load_moduleотсутствует в пакете Ubuntu. - Диск заполнен — pid/лог не пишется, unit падает после fork.
Диагностика
Плейсхолдеры: site.example, 10.0.20.40, webroot /var/www/site.example.
1. Тест конфига, не рестарт
sudo nginx -t
sudo nginx -T 2>/dev/null | grep -E 'server_name|listen |ssl_certificate|root ' | head -n 80
systemctl status nginx --no-pager
journalctl -u nginx -n 80 --no-pagerРазбирайте первую строку [emerg]: она указывает файл и номер строки. Исправляйте её, не «комментируйте всё подряд».
2. Кто держит 80 и 443
sudo ss -tlnp | grep -E ':80|:443'
sudo lsof -iTCP:80 -sTCP:LISTEN
sudo lsof -iTCP:443 -sTCP:LISTEN
dpkg -l nginx apache2 | grep ^iiЕсли apache2 слушает :80, nginx с listen 80 получит (98: Address already in use). Это не «битый nginx».
3. Сертификаты, на которые ссылается vhost
sudo grep -R ssl_certificate /etc/nginx/sites-enabled /etc/nginx/conf.d
sudo ls -l /etc/letsencrypt/live/site.example/
sudo openssl x509 -in /etc/letsencrypt/live/site.example/fullchain.pem -noout -dates -subjectПустой live/ после неудачного certbot — типичный [emerg] cannot load certificate. Не запускайте certbot --force-renewal, пока не поняли, почему выпуск сорвался: продление.
4. Include и битые симлинки
ls -l /etc/nginx/sites-enabled/
readlink -f /etc/nginx/sites-enabled/*
sudo nginx -T 2>&1 | grep 'No such file'sites-enabled/site.example → удалённый sites-available даёт emerg при старте.
5. Диск и pid
df -h / /var
ls -l /run/nginx.pid /var/log/nginx/Решение
Перед правкой:
sudo tar -C /etc -czf /root/nginx-etc-$(date +%F).tar.gz nginxСценарий A. nginx -t красный
Откройте файл из сообщения. Частые опечатки: лишняя } , забытая ;, proxy_pass http://127.0.0.1:3000 без upstream при least_conn. Исправьте одну ошибку, снова nginx -t. Когда тест OK:
sudo systemctl start nginx
sudo systemctl enable nginxСценарий B. Порт занят Apache
Либо остановите Apache, если сайт должен жить на nginx, либо уберите listen 80 у nginx, если Apache — фронт. Не держите оба на одном IP:порту.
sudo systemctl stop apache2
sudo systemctl disable apache2
sudo nginx -t && sudo systemctl start nginxЕсли Apache нужен для другого vhost — разведите IP или порт, не «убивайте» его без заявки.
Сценарий C. Нет файла сертификата, а listen 443 ssl уже в конфиге
Временно слушайте только 80 или уберите ssl-server до выпуска сертификата. Затем штатный certbot:
sudo certbot certonly --webroot -w /var/www/site.example -d site.example -d www.site.exampleВ ssl_certificate должен быть fullchain.pem, в ключе — privkey.pem. После появления файлов снова nginx -t и reload.
Минимальный каркас HTTP для выпуска, если 443 ломает старт:
server {
listen 80;
listen [::]:80;
server_name site.example www.site.example;
root /var/www/site.example;
location /.well-known/acme-challenge/ { }
}Сценарий D. Docker/NPM занял 80
docker ps и ss покажут docker-proxy. Либо публикуйте NPM на другом IP, либо не ставьте системный nginx на те же порты. См. Nginx Proxy Manager.
Сценарий E. Два default_server
Оставьте один default_server на listen 80 и один на 443. Остальным vhost — явный server_name site.example.
Как проверить, что проблема устранена
sudo nginx -t
systemctl is-active nginx
sudo ss -tlnp | grep -E ':80|:443'
curl -sI --resolve site.example:80:10.0.20.40 http://site.example/ | head
curl -skI --resolve site.example:443:10.0.20.40 https://site.example/ | headОжидание: unit active, порты слушаются процессом nginx, HTTP отдаёт 200/301, не connection refused. PHP при этом может ещё давать 502 — это другая статья.
Если не помогло
- Тест зелёный, start падает через секунду: AppArmor профиль nginx, смотрите
dmesg | grep DENIED, не отключайте AppArmor навсегда. unknown directive— пакет Ubuntu без модуля (echo,headers-more). Ставьте модуль из репозитория или уберите директиву.- После обновления пакета сломался сторонний
nginx.orgvsnginxиз Ubuntu — смотритеnginx -vи пути/etc/nginx. - Конфиг в
/etc/nginx/nginx.confпереопределён include из/etc/nginx/modules-enabled/.
Профилактика
- Любое изменение —
nginx -tзатемreload, неrestartбез нужды. - Бэкап
/etc/nginxв ту же заявку, что и правка. - Не храните единственную копию
privkeyтолько в/tmp. - Мониторинг:
systemctl is-active nginxи кодnginx -tв cron с алертом, не молчаливый|| true. - Один фронт на 80/443: либо nginx, либо Apache, либо NPM.
FAQ
Можно ли killall nginx и запустить бинарник вручную?
Нет как штатный путь. systemd потеряет pid, socket activation и log. Чините unit.
Почему nginx -t OK от sudo, а без sudo ругается на ключ?
Тест без root не читает privkey.pem (права 600). Для диагностики используйте sudo nginx -t.
Нужно ли daemon off в пакете Ubuntu?
Нет. Unit сам управляет демоном. daemon off в основном конфиге ломает ожидания systemd.
Конфликт IPv6 listen [::]:80 и listen 80
На части сборок listen 80 уже dual-stack. Дубль даёт 98. Оставьте один стиль, как в дефолтном пакете.
После certbot nginx не поднимается
Плагин мог вписать пути до успешного выпуска. Проверьте, что fullchain.pem существует, и не используйте --force-renewal как «лечение старта».