SSD Nodes Learn Hosting plans →
गाइड Matt Connorलेखक: Matt Connor · अपडेट किया गया: 2026-09-05

Nginx 403 error और SELinux को कैसे ठीक करें

यदि Nginx पर 403 error आ रहा है और permissions सही हैं तो यह SELinux का कारण हो सकता है। audit.log की जाँच करें और semanage व restorecon का उपयोग करके लेबल ठीक करें।

nginx किसी फाइल पर 403 error क्यों देता है जबकि उसकी permissions सही हैं

यदि फाइल की permission bits सही होने के बावजूद nginx 403 error दे रहा है, तो इसका कारण लगभग हमेशा SELinux (Security-Enhanced Linux) द्वारा read access को अस्वीकार करना होता है। सामान्य permissions के सफल होने के बाद SELinux नियमों का एक दूसरा सेट जाँचता है, और web server को केवल उन्हीं फाइलों को पढ़ने की अनुमति होती है जिन पर web content label लगा हो। आपकी फाइल पर एक अलग label लगा है, इसलिए open operation विफल हो जाता है और nginx के पास भेजने के लिए कोई डेटा नहीं होता।

केवल mode ही नहीं, बल्कि label की भी जाँच करें:

ls -ldZ /data/www /data/www/index.html
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /data/www
-rw-r--r--. root root unconfined_u:object_r:default_t:s0 /data/www/index.html

drwxr-xr-x के बाद छपा हुआ बिंदु (dot) यह दर्शाता है कि फाइल पर SELinux label लगा है। default_t वह label है जो किसी path को तब मिलता है जब policy में उसके बारे में कोई जानकारी न हो, और web server के नियमों में उस प्रकार की फाइल को पढ़ने की अनुमति नहीं होती। error log में एक सामान्य Unix error दिखाई देती है, इसीलिए यह permissions की समस्या जैसा प्रतीत होता है:

2026/08/11 09:14:02 [error] 1183#1183: *1 open() "/data/www/index.html" failed (13: Permission denied), client: 203.0.113.9, server: _, request: "GET / HTTP/1.1"

kernel दोनों प्रकार के इनकार (सामान्य और SELinux) के लिए 13: Permission denied ही लौटाता है। इसलिए, पहला काम यह पता लगाना है कि किस layer ने मना किया है। setenforce 0 से शुरुआत न करें।

मॉडल का वह हिस्सा जिसकी आपको आवश्यकता है

SELinux एक अनिवार्य एक्सेस कंट्रोल है, जिसे आमतौर पर MAC लिखा जाता है। प्रत्येक process एक domain में चलती है, जैसे कि web server के लिए httpd_t। प्रत्येक file और प्रत्येक network port पर एक type होता है, जैसे कि httpd_sys_content_t। policy domain, type और action के स्वीकृत संयोजनों की एक सूची है, और जो कुछ भी उस सूची में नहीं है, उसे अस्वीकार कर दिया जाता है। यह क्लासिक Unix जाँच के बाद चलता है, इसलिए drwxr-xr-x में permission bits को पहले एक्सेस की अनुमति देनी होगी। दोनों परतों का 'हाँ' कहना आवश्यक है।

एक पूर्ण context में कोलन द्वारा अलग किए गए चार fields होते हैं, जैसे system_u:system_r:httpd_t:s0: SELinux user, role, type, और level। एक server पर आप अपना लगभग सारा समय तीसरे field, यानी type पर बिताएंगे। दो commands लाइव values दिखाती हैं:

ps -eZ | grep nginx
id -Z

nginx workers एक context दिखाते हैं जो httpd_t पर समाप्त होता है। आपका login shell unconfined_u:unconfined_r:unconfined_t:s0 दिखाता है, क्योंकि डिफ़ॉल्ट targeted policy services को सीमित करती है और interactive users को स्वतंत्र छोड़ देती है। यह जानना महत्वपूर्ण है, क्योंकि SELinux least-privilege users के अंतर्गत services चलाने का विकल्प नहीं है। यह केवल यह सीमित करता है कि किसी के द्वारा breach किए जाने के बाद service कहाँ तक पहुँच सकती है।

तीन मोड, और किन images में SELinux होता है

sestatus
getenforce

Enforcing मोड क्रियाओं को रोकता है और उन्हें log करता है। Permissive मोड सब कुछ करने की अनुमति देता है और केवल यह log करता है कि उसने क्या रोका होता। Disabled मोड कोई policy लोड नहीं करता है। getenforce वर्तमान मोड को print करता है। sestatus भी /etc/selinux/config से मोड को print करता है, जो वह मोड है जो reboot के बाद वापस आता है।

Rocky Linux, AlmaLinux, Fedora और RHEL, SELinux को targeted policy के साथ enforcing मोड में ship करते हैं। यह साझा default संयोग नहीं बल्कि विरासत है, क्योंकि ये चारों उसी Red Hat lineage से निकले हैं जो Rocky Linux और AlmaLinux के आने से पहले CentOS के माध्यम से चलती थी। आप इनमें से कौन सा OS चलाते हैं, इससे इस पृष्ठ पर दी गई किसी भी चीज़ में कोई अंतर नहीं आता, क्योंकि वे समान policy और समान tools के साथ आते हैं। इसलिए Rocky Linux और AlmaLinux के बीच चुनाव सुरक्षा defaults के बजाय उनके compatibility वादों और पुराने CPU support पर निर्भर करता है। Ubuntu और Debian इसके बजाय AppArmor के साथ आते हैं, जो एक अलग तंत्र के साथ वही काम करता है (अंतिम खंड इसे कवर करता है)। इसलिए एक ही application आपके एक सर्वर पर ठीक से install हो सकती है और दूसरे पर 403 error दे सकती है।

जरूरत पड़ने से पहले टूल्स इंस्टॉल करें

sudo dnf install -y policycoreutils-python-utils setroubleshoot-server

Minimal image पर semanage: command not found का मतलब है कि policycoreutils-python-utils गायब है: उस पैकेज में semanage और audit2allow शामिल होते हैं। setroubleshoot-server, sealert को जोड़ता है और प्रत्येक denial का एक सरल अंग्रेजी सारांश journal में लिखता है। इन्हें एक नए सर्वर पर इंस्टॉल करें, क्योंकि जिस क्षण आपको इनकी आवश्यकता होती है, उसी क्षण कुछ न कुछ पहले से ही खराब हो चुका होता है।

SELinux denial को audit log में कैसे पढ़ें

प्रत्येक इनकार (refusal) को audit daemon द्वारा एक AVC (access vector cache) संदेश के रूप में रिकॉर्ड किया जाता है:

sudo ausearch -m AVC,USER_AVC,SELINUX_ERR -ts recent
type=AVC msg=audit(1754896442.881:412): avc:  denied  { read } for  pid=1183 comm="nginx" name="index.html" dev="vda1" ino=17203 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0

चार fields पूरी कहानी बयां करते हैं। comm वह प्रोग्राम है जिसे ब्लॉक किया गया था। scontext source context है, वह domain जिसमें process चल रही थी। tcontext target context है, उस वस्तु पर लगा label जिसे वह छूने की कोशिश कर रही थी। tclass object का प्रकार है, यहाँ एक file। इन्हें एक साथ पढ़ें: httpd_t में मौजूद process ने default_t लेबल वाली file को पढ़ने की कोशिश की, और permissive=0 बताता है कि अनुरोध को वास्तव में ब्लॉक किया गया था, न कि केवल log किया गया था।

यदि ausearch कुछ भी print नहीं करता है, तो हो सकता है कि audit daemon न चल रहा हो। ऐसी स्थिति में denials kernel ring buffer में चले जाते हैं:

sudo journalctl -k | grep -i avc

अब रिकॉर्ड को एक वाक्य में बदलें:

sudo ausearch -m AVC -ts recent | audit2why
sudo journalctl -t setroubleshoot --since today
sudo sealert -a /var/log/audit/audit.log

audit2why उन्हीं रिकॉर्ड्स को पढ़ता है और पहचाने गए कारण का नाम बताता है: एक boolean जो बंद है, एक label जो policy से मेल नहीं खाता, या कोई नियम ही नहीं है। sealert पूरे log को स्कैन करता है और प्रत्येक denial के लिए एक सुझाया गया command print करता है। सुझाव को केवल एक संकेत मानें। releases के बीच शब्दावली बदलती रहती है, और sealert कभी-कभी एक custom policy module का प्रस्ताव देता है, जबकि सही समाधान केवल एक-लाइन का label fix हो सकता है।

एक और बात ध्यान रखें। Policy में dontaudit नियम होते हैं जो उन denials को छिपा देते हैं जिन्हें हानिरहित माना जाता है, इसलिए एक प्रोग्राम गलत व्यवहार कर सकता है जबकि log खाली रहता है। एक परीक्षण की अवधि के लिए उन्हें unhide करें:

sudo semodule -DB
# reproduce the problem, then read the log again
sudo semodule -B

semanage fcontext और restorecon के साथ गलत लेबल वाले पाथ को ठीक करना

दो commands का उपयोग करें, और उनका क्रम महत्वपूर्ण है। semanage fcontext -a यह रिकॉर्ड करता है कि किसी पाथ का लेबल क्या होना चाहिए। restorecon उस रिकॉर्ड किए गए डिफ़ॉल्ट को डिस्क पर मौजूद फाइलों पर लागू करता है।

sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
sudo restorecon -Rv /data/www
ls -ldZ /data/www/index.html

पाथ एक रेगुलर एक्सप्रेशन होता है। (/.*)? डायरेक्टरी और उसके अंदर की हर चीज़ को कवर करता है, जो कि एक डॉक्यूमेंट रूट के लिए आवश्यक है। बदलाव करने से पहले देखें कि क्या बदलेगा: sudo restorecon -Rvn /data/www नियोजित रीलेबल को प्रिंट करता है, क्योंकि -n का अर्थ है कि कोई कार्रवाई नहीं होगी। वास्तविक restorecon के बाद लेबल httpd_sys_content_t हो जाता है और बिना सर्विस रीस्टार्ट किए 403 एरर हट जाता है।

chcon का उपयोग केवल परीक्षण के लिए करें। chcon -t httpd_sys_content_t index.html लेबल को सीधे सेट करता है, और अगला restorecon, पैकेज अपडेट या पूर्ण रीलेबल इसे रीसेट कर देता है, क्योंकि पॉलिसी अभी भी कहती है कि पाथ कुछ और होना चाहिए। ऐसे सिस्टम पर जहाँ dnf-automatic एक टाइमर पर सुरक्षा अपडेट लागू करता है, वह रीसेट अपने आप एक निर्धारित समय पर हो जाता है, न कि तब जब आप मशीन के सामने बैठे हों, इसलिए आपके द्वारा अंतिम बदलाव करने के कुछ घंटों बाद साइट बंद हो जाती है। semanage fcontext वह वर्ज़न है जो बना रहता है। जो आपने रिकॉर्ड किया है उसे sudo semanage fcontext -l | grep '^/data' के साथ लिस्ट करें।

जिस कंटेंट को सर्विस को लिखना है, उसके लिए एक अलग टाइप की आवश्यकता होती है। अपलोड डायरेक्टरी या कैश के लिए httpd_sys_rw_content_t का उपयोग करें, और इसे केवल उन्हीं पाथ तक सीमित रखें: राइटेबल टाइप के अंतर्गत रीड-ओनली साइट एप्लिकेशन की आवश्यकता से अधिक एक्सेस प्रदान करती है।

लेबल गलत क्यों था? लगभग हमेशा फाइलों के आने के तरीके के कारण। mv फाइल के मौजूदा लेबल को बनाए रखता है, इसलिए /root से बाहर ले जाई गई साइट admin_home_t लेबल के साथ आती है और वैसी ही बनी रहती है। एक साधारण cp नई फाइल को डेस्टिनेशन डायरेक्टरी का डिफ़ॉल्ट लेबल देता है, जो आमतौर पर आप चाहते हैं, जबकि cp -a और rsync -X फाइल के साथ सोर्स लेबल को भी कॉपी करते हैं। एक नई टॉप-लेवल डायरेक्टरी में git clone करने से default_t प्राप्त होता है। जब कोई पेज /usr/share/nginx/html से ठीक से लोड होता है और आपकी अपनी डायरेक्टरी से विफल हो जाता है, तो यही इसका कारण है।

Boolean का उपयोग करके व्यवहार की एक श्रेणी को ठीक करना

कुछ विफलताएं लेबल की समस्या नहीं होती हैं। एक नए Rocky या AlmaLinux बॉक्स पर reverse proxy 502 error देता है, और error log में यह दिखाई देता है:

2026/08/11 10:02:55 [crit] 1183#1183: *3 connect() to 127.0.0.1:3000 failed (13: Permission denied) while connecting to upstream

आपका upstream ठीक है। httpd_t domain को डिफ़ॉल्ट रूप से outbound network connections खोलने की अनुमति नहीं है, इसलिए connect() कॉल loopback interface तक पहुँचने से पहले ही अस्वीकार कर दी जाती है। एक स्विच इस पूरे व्यवहार को नियंत्रित करता है:

getsebool -a | grep httpd_can_network
sudo setsebool -P httpd_can_network_connect on

-P वह flag है जो मायने रखता है: यह मान को disk पर लिखता है। -P के बिना, अगली बार reboot करने पर बदलाव खो जाता है, जिससे आपको एक ऐसी service मिलती है जो मशीन के restart होने तक काम करती है। semanage boolean -l | grep httpd_can_network_connect के साथ पुष्टि करें, जो संग्रहीत मान के बगल में चल रहे मान को print करता है।

जब भी कोई विकल्प मौजूद हो, तो हाथ से लिखे गए rule के बजाय boolean को प्राथमिकता दें। Booleans distribution policy के साथ आते हैं, इसलिए उन्हें maintain किया जाता है, document किया जाता है, और अगले व्यक्ति के लिए ढूँढना आसान होता है। getsebool -a सिस्टम पर मौजूद हर एक को सूचीबद्ध करता है।

किसी service को non-standard port पर listen करने दें

Ports को भी label किया जाता है। Nginx को 8081 पर ले जाने पर वह start होने से मना कर देता है:

nginx: [emerg] bind() to 0.0.0.0:8081 failed (13: Permission denied)

httpd_t केवल उन ports को bind कर सकता है जो http_port_t के रूप में label किए गए हों, और 8081 उनमें से एक नहीं है। इसे जोड़ें:

sudo semanage port -l | grep -w http_port_t
sudo semanage port -a -t http_port_t -p tcp 8081

पहले सूची की जाँच करें। कई high ports पहले से ही allowed हैं, जिनमें 8008 और 8443 शामिल हैं, और किसी को दो बार जोड़ने पर ValueError: Port tcp/8081 already defined के साथ failure मिलता है। यदि port पहले से ही किसी अन्य प्रकार से संबंधित है, तो उसे जोड़ने के बजाय semanage port -m -t http_port_t -p tcp 8081 के साथ बदलें।

यही command बदले हुए SSH port को काम करने योग्य बनाती है। journalctl -u sshd में Bind to port 2222 on 0.0.0.0 failed: Permission denied का मतलब है कि 2222, ssh_port_t में मौजूद नहीं है, इसलिए daemon को restart करने और अपना session बंद करने से पहले sudo semanage port -a -t ssh_port_t -p tcp 2222 चलाएँ। यह वह चरण है जिसे लोग तब छोड़ देते हैं जब वे VPS पर SSH को सुरक्षित करने के लिए किसी सामान्य guide का पालन करते हैं, विशेषकर Red Hat परिवार की image पर। SELinux कोई firewall नहीं है, इसलिए port को अभी भी open होना चाहिए: यहाँ sudo firewall-cmd --permanent --add-port=8081/tcp && sudo firewall-cmd --reload, या Debian या Ubuntu image पर ufw का उपयोग करें। वह --permanent flag वही reboot trap रखता है जो boolean पर -P का होता है, और वे zones जो यह तय करते हैं कि कोई rule किन interfaces पर लागू होता है, उन्हें Rocky या AlmaLinux VPS के लिए firewalld की बुनियादी बातें में एक बार पढ़ना उपयोगी है।

जब बदलने के लिए कोई boolean या label न हो

एक सामान्य सर्वर पर ऐसा कम ही होता है, और यहीं पर लोग नुकसान पहुँचाते हैं। audit2allow लॉग में मौजूद denials से एक policy module बना सकता है:

sudo ausearch -m AVC -ts recent -c nginx | audit2allow -M nginx_local
cat nginx_local.te
sudo semodule -i nginx_local.pp

इसे install करने से पहले nginx_local.te को पढ़ें। दो आदतें इसे सुरक्षित रखती हैं। इनपुट को केवल उस एक प्रोग्राम तक सीमित करें जिसे आप ठीक कर रहे हैं, इसके लिए -c का उपयोग करें, क्योंकि एक सप्ताह के असंबंधित denials को audit2allow में पाइप करने से वे सभी एक साथ अनुमति प्राप्त कर लेंगे। और कभी भी ऐसे denial से बना module install न करें जिसे आप समझा न सकें: एक ऐसा नियम जो httpd_t को बॉक्स पर मौजूद हर फाइल को पढ़ने की अनुमति देता है, उसे बनाना आसान है लेकिन महीनों बाद उसे पहचानना मुश्किल होता है। sudo semodule -r nginx_local के साथ module को हटा दें।

Permissive एक डायग्नोस्टिक मोड है, समाधान नहीं

sudo setenforce 0
# reproduce the problem once, all the way through
sudo ausearch -m AVC -ts recent
sudo setenforce 1

Permissive मोड एक्सेस की अनुमति देता है और उसे लॉग करता है। इसका वास्तविक मूल्य इसकी पूर्णता में है। Enforcing मोड में, सर्विस पहले denial पर ही रुक जाती है, इसलिए आप उसे ठीक करते हैं, रीस्टार्ट करते हैं, और फिर दूसरे denial का सामना करते हैं। Permissive मोड में, रन जारी रहता है और लॉग एक ही बार में हर denial को इकट्ठा कर लेता है, जिसके बाद आप वापस स्विच करके उन्हें एक साथ ठीक कर सकते हैं।

setenforce, /etc/selinux/config को प्रभावित नहीं करता है, इसलिए रीबूट करने पर सिस्टम वापस enforcing मोड में आ जाता है। यह एक सुरक्षा कवच है, और यही कारण है कि setenforce 0 से किया गया "समाधान" सबसे खराब समय पर फिर से सामने आ जाता है। यदि काम करते समय किसी एक सर्विस को छूट की आवश्यकता हो, तो पूरी मशीन के बजाय केवल उस डोमेन को मार्क करें: sudo semanage permissive -a httpd_t बाकी सब कुछ enforcing रखता है, और sudo semanage permissive -d httpd_t इसे वापस सामान्य कर देता है।

SELinux को disable करना, label ठीक करने की तुलना में अधिक महंगा क्यों है

/etc/selinux/config में SELINUX=disabled सेट करना, एक लाइन के label फिक्स को हमेशा के लिए एक कमजोर सर्वर से बदलने जैसा है। इसका अंतर उस दिन पता चलता है जब कोई web application breach हो जाती है। Enforcing मोड में, attacker का कोड httpd_t में चलता है, इसलिए वह web content तो पढ़ सकता है, लेकिन Unix user की अनुमति होने के बावजूद policy उसे /etc/shadow पढ़ने या systemd unit लिखने से रोक देती है। यदि कोई policy loaded न हो, तो वही कोड उन सभी चीजों तक पहुँच जाता है जो service account के पास हैं।

इसे disable करने की कीमत आपको बाद में चुकानी पड़ती है। जब कोई policy loaded नहीं होती, तो नई फाइलें बिना label के बनती हैं, जिससे filesystem और policy के बीच तालमेल बिगड़ जाता है। SELinux को वापस चालू करने पर या तो पूरा relabel करना पड़ता है, या एक साथ कई services fail हो जाती हैं:

sudo fixfiles -F onboot
sudo reboot

यह /.autorelabel लिखता है और अगले boot के दौरान हर filesystem को relabel करता है। बड़ी disk पर इसमें काफी समय लगता है और console रुका हुआ प्रतीत होता है, इसलिए इसे तब शुरू करें जब आप प्रतीक्षा कर सकें। चूंकि मशीन वैसे भी बंद होने वाली है, इसलिए यह देखना उचित है कि restart के लिए और क्या कतार में है, जो कि dnf update के बाद old kernels और libraries के memory में रह जाने पर needs-restarting द्वारा रिपोर्ट किया जाता है। Rocky Linux और AlmaLinux 9 पर config फाइल अब kernel के हिस्से को अपने आप बंद नहीं करती है, और SELinux को पूरी तरह से disable करने का documented तरीका एक kernel argument (sudo grubby --update-kernel ALL --args selinux=0) है। उस command को जानना तब काम आता है जब आप किसी और का सर्वर संभालते हैं। यह 403 error का समाधान नहीं है।

Containers में एक और label जोड़ना

Red Hat परिवार के host पर, container processes container_t में चलते हैं और केवल container_file_t label वाली फाइलें ही पढ़ सकते हैं। Host से bind mount करने पर container के अंदर Permission denied error आता है, जबकि host पर ls -l बिल्कुल सामान्य दिखता है। :Z suffix runtime को mount को relabel करने का निर्देश देता है:

docker run -d -v /data/appdata:/var/lib/app:Z myimage

:Z इस directory को केवल इसी container के लिए label करता है। :z इसे containers के बीच साझा करने के लिए label करता है। यदि आप :Z को ऐसी directory पर point करते हैं जिसका उपयोग अन्य services करती हैं, तो यह उस directory को recursively relabel कर देता है, जिससे वे services काम करना बंद कर देती हैं। इसलिए, containers को उनके अपने paths दें। यदि engine अभी तक box पर नहीं है, तो ध्यान दें कि इन distributions पर docker command अक्सर podman होती है जो इस नाम से जवाब देती है। यह एक ऐसी बारीकी है जिसे Rocky और AlmaLinux install steps में सुलझाया गया है, इससे पहले कि आप इनका सामना करें। सेटअप के बारे में बाकी सब कुछ किसी भी अन्य image से मेल खाता है, जिसे running Docker on a VPS में कवर किया गया है।

Ubuntu और Debian में AppArmor मिलता है

काम वही है, लेकिन डिज़ाइन अलग है। AppArmor किसी प्रोग्राम को उसकी executable के पाथ के आधार पर सीमित करता है, जिसके लिए /etc/apparmor.d/ के अंतर्गत एक प्रोफाइल का उपयोग किया जाता है, न कि डिस्क पर फाइलों को लेबल करने का। इसमें relabel करने के लिए कुछ नहीं होता और न ही कोई restorecon होता है। यहाँ से शुरुआत करें:

sudo aa-status
sudo journalctl -k | grep -i apparmor

एक इनकार (refusal) apparmor="DENIED" operation="open" profile="/usr/sbin/nginx" name="/data/www/index.html" requested_mask="r" के रूप में दिखाई देता है। कार्यप्रवाह (workflow) का स्वरूप वही है: इनकार को पढ़ें, प्रोफाइल ढूँढें, नियम बदलें। sudo apt install apparmor-utils आपको aa-complain (एक प्रोफाइल के लिए permissive) और इसे वापस लाने के लिए aa-enforce की सुविधा देता है। Ubuntu पैक्ड सेवाओं के एक चयनित सेट को ही सीमित करता है और बाकी को unconfined छोड़ देता है, इसलिए यह मान लेने के बजाय कि क्या सक्रिय है, वास्तव में क्या सक्रिय है यह देखने के लिए aa-status पढ़ें।

एक आदत दोनों सिस्टम में समान रहती है। जब कोई सेवा किसी ऐसी चीज़ पर Permission denied रिपोर्ट करती है जो सही दिखती है, तो अनुमतियों (permissions) को बदलने से पहले सुरक्षा लॉग पढ़ें। समस्या शायद ही कभी दो बार बिट्स (bits) के कारण होती है।

FAQ

यदि file permissions सही हैं, तो भी nginx 403 error क्यों देता है?

ऐसा इसलिए होता है क्योंकि SELinux ने access को deny किया है, न कि permission bits ने। Web server httpd_t domain में चलता है और केवल उन्हीं files को पढ़ सकता है जिन्हें web content के लिए label किया गया है। इसलिए, यदि किसी file पर default_t या admin_home_t label है, तो उसे access करने से मना कर दिया जाता है और nginx के पास serve करने के लिए कुछ नहीं होता। इसकी पुष्टि sudo ausearch -m AVC -ts recent से करें, जो यह दिखाएगा कि scontext का अंत httpd_t पर हो रहा है और tcontext में गलत type मौजूद है। इसके बाद सही label को record करें और उसे लागू करें: sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?" और उसके बाद sudo restorecon -Rv /data/www चलाएं।

क्या किसी service को चलाने के लिए setenforce 0 का उपयोग करना सुरक्षित है?

setenforce 0 केवल एक diagnostic step है, समाधान नहीं। इसका उपयोग समस्या को एक बार reproduce करने के लिए करें ताकि log में सभी denials एक साथ आ जाएं, फिर उन्हें sudo ausearch -m AVC -ts recent से पढ़ें, और अंत में sudo setenforce 1 चलाकर कारणों को ठीक करें। यदि server को permissive mode में छोड़ दिया जाता है, तो वह हर denial को log तो करेगा लेकिन किसी को block नहीं करेगा; इससे logs में अनावश्यक जानकारी बढ़ेगी और सुरक्षा खत्म हो जाएगी। यदि काम करते समय किसी एक service को छूट देने की आवश्यकता हो, तो sudo semanage permissive -a httpd_t चलाएं ताकि बाकी machine enforcing mode में बनी रहे।

SELinux enforcing mode में किसी service को non-standard port पर कैसे चलाएं?

उस port को उस type में जोड़ें जिसे वह service bind करने के लिए अधिकृत है। 8081 port पर web server के लिए: sudo semanage port -a -t http_port_t -p tcp 8081। 2222 port पर SSH के लिए: sudo semanage port -a -t ssh_port_t -p tcp 2222। पहले sudo semanage port -l | grep -w http_port_t के साथ वर्तमान सूची की जांच करें, क्योंकि यदि port पहले से ही सूची में है, तो ValueError: Port tcp/8081 already defined error आएगा। इस step के बिना, daemon startup के समय bind() ... Permission denied error के साथ बंद हो जाएगा, भले ही कोई अन्य process उस port का उपयोग न कर रही हो।

क्या Ubuntu में SELinux होता है?

नहीं। Ubuntu और Debian में AppArmor होता है, जो files पर labels के बजाय executable के path से जुड़े profile को लागू करता है। इसकी जांच sudo aa-status से करें और sudo journalctl -k में apparmor="DENIED" lines को देखें। Ubuntu केवल चुनिंदा packaged services को ही confine करता है, इसलिए डिफ़ॉल्ट रूप से कई programs unconfined चलते हैं। Rocky Linux और AlmaLinux में, Fedora और RHEL के साथ, आपको SELinux enforcing mode पहले से ही मिलता है।