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:

html
Forbidden
You don't have permission to access /path on this server.
Apache/2.4 Server at example.com Port 80

Apache error log:

```bash tail -f /var/log/apache2/error.log

AH01630: client denied by server configuration: /var/www/html/ ```

Why This Happens

  1. 1.File permissions - Apache user cannot read file
  2. 2.Directory permissions - Directory not executable
  3. 3.Require directive - Access control denying
  4. 4.Options -Indexes - Directory listing disabled
  5. 5.FollowSymLinks - Symlink not followed
  6. 6.SELinux context - Wrong SELinux context
  7. 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

CheckCommandExpected
Error logstail error.logSpecific error
File permissionsls -la644 for files
Directory permissionsls -la755 for dirs
Directory configapache2.confRequire granted
SELinux (if used)getenforceCorrect context
Virtual hostsites-enabledAccess 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 ```

  • [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)