Trong quá trình rà soát các vấn đề bảo mật trên hệ thống, tôi đã phát hiện ra rằng khi thêm tùy chọn user và group vào file cấu hình systemd của Nginx:
/etc/systemd/system/nginx.service
thì gặp phải lỗi khi khởi động:
the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /usr/local/nginx/nginx.conf:1
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
<br></br>User=www
Group=www
[Install]
WantedBy=multi-user.target
Tuy nhiên, trong file cấu hình nginx.conf:
user www;
worker_processes 1;
cài đặt thực sự là người dùng cho các tiến trình worker của Nginx, không phải tiến trình master
root 37796 1 0 09:50 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/nginx.conf
www 37797 37796 0 09:50 ? 00:00:00 nginx: worker process
root 38546 38413 0 10:09 pts/1 00:00:00 grep --color=auto nginx
Mặc định trong Linux, các cổng dưới 1024 chỉ có người dùng root mới có quyền sử dụng, đây là lý do Nginx thường sử dụng cổng 80 và 443
Ngay cả khi bạn chỉ định người dùng www trong file nginx.service, hệ thống vẫn sẽ báo lỗi vì không thể khởi động dịch vụ trên các cổng 80 và 443.
Giải pháp đơn giản là bạn chỉ cần comment lại các dòng User và Group:
#User=www
#Group=www
và các dịch vụ khác như Elasticsearch hay PHP-FPM có thể thêm tùy chọn này một cách trực tiếp.
Lưu ý: Sau khi sửa đổi file .service, bạn cần chạy lệnh systemctl daemon-reload để áp dụng thay đổi.
Ví dụ về script khởi động của Elasticsearch:
[Service]
Type=notify
RuntimeDirectory=elasticsearch
PrivateTmp=true
Environment=ES_HOME=/usr/share/elasticsearch
Environment=ES_PATH_CONF=/etc/elasticsearch
Environment=PID_DIR=/var/run/elasticsearch
Environment=ES_SD_NOTIFY=true
EnvironmentFile=-/etc/sysconfig/elasticsearch
WorkingDirectory=/usr/share/elasticsearch
User=elasticsearch
Group=elasticsearch
ExecStart=/usr/share/elasticsearch/bin/systemd-entrypoint -p ${PID_DIR}/elasticsearch.pid --quiet
# StandardOutput is configured to redirect to journalctl since
# some error messages may be logged in standard output before
# elasticsearch logging system is initialized. Elasticsearch
# stores its logs in /var/log/elasticsearch and does not use
# journalctl by default. If you also want to enable journalctl
# logging, you can simply remove the "quiet" option from ExecStart.
StandardOutput=journal
StandardError=inherit
# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65535
# Specifies the maximum number of processes
LimitNPROC=4096
# Specifies the maximum size of virtual memory
LimitAS=infinity
# Specifies the maximum file size
LimitFSIZE=infinity
# Disable timeout logic and wait until process is stopped
TimeoutStopSec=0
# SIGTERM signal is used to stop the Java process
KillSignal=SIGTERM
# Send the signal only to the JVM rather than its control group
KillMode=process
# Java process is never killed
SendSIGKILL=no
# When a JVM receives a SIGTERM signal it exits with code 143
SuccessExitStatus=143
# Allow a slow startup before the systemd notifier module kicks in to extend the timeout
TimeoutStartSec=75
[Install]
WantedBy=multi-user.target
View CodeScript khởi động của PHP-FPM:
[Unit]
Description=php8-fpm
After=syslog.target network.target
[Service]
Type=simple
PIDFile=/usr/local/php8/php-fpm.pid
ExecStart=/usr/local/php8/sbin/php-fpm -c /usr/local/php8/etc/php.ini -y /usr/local/php8/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID
User=www
Group=www
[Install]
WantedBy=multi-user.target
Các giải pháp thay thế khác:
Phương án 1:
Cho phép tất cả người dùng chạy (vì quyền 755, chủ sở hữu: root, nhóm sở hữu: root)
chown root.root ./nginx/
chmod 755 ./nginx/
chmod u+s ./nginx/
Phương án 2:
Chỉ cho phép người dùng root và wyq chạy (vì quyền 750, chủ sở hữu: root, nhóm sở hữu: www)
chown root.www ./nginx/
chmod 750 ./nginx/
chmod u+s ./nginx/