When configuring symlinks or aliases in Apache HTTPD on macOS, simply setting chmod 755
on the target directory isn't always sufficient. The error messages you're seeing:
[error] [client ::1] (13)Permission denied: access to /foo denied
Symbolic link not allowed or link target not accessible
indicate deeper permission issues in the directory hierarchy.
Apache's www user (typically _www on macOS) needs execute permissions on:
- The target directory itself
- Every parent directory in the path
- The symlink if using that approach
For the Alias method to work:
# Fix permissions for the entire path
chmod 755 ~
chmod 755 ~/Documents
chmod 755 ~/Documents/foo
chmod 755 ~/Documents/foo/html
# Verify the permissions
ls -ld ~ ~/Documents ~/Documents/foo ~/Documents/foo/html
If using symlinks, ensure these Apache directives are set:
<Directory "/Library/WebServer/Documents">
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
And verify symlink permissions:
ln -s ~/Documents/foo/html /Library/WebServer/Documents/foo
chmod 755 /Library/WebServer/Documents/foo
If issues persist:
- Check Apache's user/group configuration:
ps aux | grep httpd cat /etc/apache2/httpd.conf | grep User
- Verify directory ownership:
sudo chown -R $(whoami):_www ~/Documents/foo chmod -R 775 ~/Documents/foo
- Check SELinux context (if applicable):
ls -Z /Library/WebServer/Documents/foo
For more complex setups, consider:
# Virtual Host configuration
<VirtualHost *:80>
DocumentRoot "/Users/someone/Documents/foo/html"
ServerName foo.localhost
<Directory "/Users/someone/Documents/foo/html">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Remember to add to /etc/hosts
:
127.0.0.1 foo.localhost
When attempting to expose a user directory (like ~/Documents/foo/html
) through Apache's Alias
directive or symlinks, macOS presents unique permission hurdles. The key insight is that every parent directory in the path must be executable (searchable) by the _www
user (Apache's default user on macOS).
# Verify current permissions
ls -ld ~/ ~/Documents/ ~/Documents/foo/ ~/Documents/foo/html/
# Apply recursive permissions (minimum)
chmod 755 ~/Documents
chmod -R 755 ~/Documents/foo/html
For the Alias approach, ensure your httpd.conf
contains:
<VirtualHost *:80>
ServerName localhost
# Essential directives
DocumentRoot "/Library/WebServer/Documents"
<Directory "/Library/WebServer/Documents">
Options +Indexes +FollowSymLinks +MultiViews
AllowOverride All
Require all granted
</Directory>
# Your custom alias
Alias /foo "/Users/someone/Documents/foo/html"
<Directory "/Users/someone/Documents/foo/html">
Options +Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
When using symlinks in /Library/WebServer/Documents
:
# Create symlink properly
sudo ln -s ~/Documents/foo/html /Library/WebServer/Documents/foo
# Verify ownership
ls -l /Library/WebServer/Documents/foo
# Should show:
# lrwxr-xr-x 1 root wheel 39B Jan 1 12:00 foo -> /Users/someone/Documents/foo/html
- Check Apache error log:
tail -f /var/log/apache2/error_log
- Verify directory traversal:
sudo -u _www ls /Users/someone/Documents/foo/html
- Test basic access:
curl -I http://localhost/foo/
For newer macOS versions with stricter security:
# Check if SIP is interfering
csrutil status
# Temporary test (not recommended for production)
sudo chmod -R a+rx ~/Documents