A 403 is different from a 404 in a useful way: the server found what you asked for. Something then said no. That narrows it to four things.

1. There is no index file

A request for a directory with no index.php or index.html, and directory listing off, is a 403. That is correct behaviour and usually means a deploy did not finish.

ls -la /var/www/site/

2. The server cannot read it

A file the web user cannot read is refused. Check the owner as well as the mode - the mode is fine far more often than the owner is.

namei -l /var/www/site/index.php

namei walks the whole path and prints the permissions at every level. A directory in the middle with no execute bit blocks everything below it, and that is the case people miss.

3. A rule is denying it

grep -rn "deny\|Require all denied" /etc/nginx/sites-enabled/ .htaccess 2>/dev/null

Security rules that deny by extension or by directory are the intended kind of 403. If it is your own file being caught, the rule is too broad.

4. A firewall or WAF

If the 403 comes with a page that is not yours, it is from something in front of the server. Its own log names the rule that matched.

A 403 on wp-admin after a plugin update is usually a security plugin locking a path it thinks is under attack. Its log will say so, and disabling it by renaming its directory is the quickest way to confirm.