What's Actually Happening
Apache returns 403 Forbidden when access to a resource is denied. Users cannot access files, directories, or virtual hosts due to permission issues.
The Error You'll See
403 Forbidden:
Forbidden
You don't have permission to access /path on this server.
Apache/2.4 Server at example.com Port 80Apache error log:
```bash tail -f /var/log/apache2/error.log
AH01630: client denied by server configuration: /var/www/html/ ```
Why This Happens
- 1.File permissions - Apache user cannot read file
- 2.Directory permissions - Directory not executable
- 3.Require directive - Access control denying
- 4.Options -Indexes - Directory listing disabled
- 5.FollowSymLinks - Symlink not followed
- 6.SELinux context - Wrong SELinux context
- 7..htaccess denial - Deny in .htaccess
Step 1: Check Apache Error Logs
```bash tail -f /var/log/apache2/error.log
tail -f /var/log/httpd/error_log
journalctl -u apache2 -f
journalctl -u httpd -f
grep -i "403|denied|forbidden" /var/log/apache2/error.log | tail -20 ```
Step 2: Check File Permissions
```bash ls -la /var/www/html/
ls -la /var/www/html/file.html
# Check owner: stat /var/www/html/file.html
# Fix permissions: chmod 644 /var/www/html/file.html chown www-data:www-data /var/www/html/file.html
# For directories: chmod 755 /var/www/html/ ```
Step 3: Check Directory Permissions
```bash # Each directory must be executable: ls -la /var/www/
# Fix parent directories: chmod 755 /var chmod 755 /var/www chmod 755 /var/www/html
# Check Apache user: ps aux | grep apache ps aux | grep www-data
# Test as Apache user: su -s /bin/bash www-data -c "cat /var/www/html/file.html" ```
Step 4: Check Directory Configuration
```bash cat /etc/apache2/apache2.conf | grep -A 10 Directory
cat /etc/apache2/conf-enabled/security.conf
# Directory directive: <Directory /var/www/html> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory>
# For specific directory: <Directory /var/www/html/private> Require all denied </Directory> ```
Step 5: Check Virtual Host Configuration
```bash cat /etc/apache2/sites-enabled/000-default.conf
cat /etc/apache2/sites-enabled/site.conf
# Virtual host with access: <VirtualHost *:80> ServerName example.com DocumentRoot /var/www/html
<Directory /var/www/html> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> </VirtualHost>
# Test config: apache2ctl configtest apachectl configtest ```
Step 6: Check .htaccess
```bash cat /var/www/html/.htaccess
# Common deny rules: Deny from all Require all denied
# Comment out or remove deny rules
# Check AllowOverride: # Must be All for .htaccess to work AllowOverride All ```
Step 7: Check SELinux
```bash getenforce
ls -Z /var/www/html/
# Restore context: restorecon -Rv /var/www/html/
# Set httpd context: chcon -R -t httpd_sys_content_t /var/www/html/
# Allow httpd to read: setsebool -P httpd_read_user_content 1
# Check SELinux audit: ausearch -m avc -ts recent | grep httpd ```
Step 8: Check Options Configuration
```bash # Check Options in config: grep -r "Options" /etc/apache2/
# Enable directory listing: Options +Indexes
# Enable symlinks: Options +FollowSymLinks
# Common config: <Directory /var/www/html> Options -Indexes +FollowSymLinks AllowOverride All Require all granted </Directory> ```
Step 9: Check Access Control
```bash # Old syntax (Apache 2.2): Order deny,allow Deny from all
# New syntax (Apache 2.4): Require all denied Require all granted
# By IP: Require ip 192.168.1.0/24
# By host: Require host example.com
# Mixed: <RequireAny> Require ip 192.168.1.0/24 Require host trusted.com </RequireAny> ```
Step 10: Reload Apache
```bash apache2ctl configtest
systemctl reload apache2
systemctl restart apache2
systemctl status apache2
curl -I http://localhost/file.html ```
Apache 403 Forbidden Checklist
| Check | Command | Expected |
|---|---|---|
| Error logs | tail error.log | Specific error |
| File permissions | ls -la | 644 for files |
| Directory permissions | ls -la | 755 for dirs |
| Directory config | apache2.conf | Require granted |
| SELinux (if used) | getenforce | Correct context |
| Virtual host | sites-enabled | Access allowed |
Verify the Fix
```bash curl -I http://localhost/file.html
ls -la /var/www/html/file.html
apache2ctl -S
systemctl status apache2
tail -f /var/log/apache2/error.log
curl -I http://example.com/path ```
Related Issues
- [Fix Apache 500 Internal Server Error](/articles/fix-apache-500-internal-server-error)
- [Fix Apache Virtual Host Not Working](/articles/fix-apache-virtual-host-not-working)
- [Fix Nginx 403 Forbidden](/articles/fix-nginx-403-forbidden)