Developer tools · Chmod calculator
Fixing nginx 403 Forbidden: the file and directory permissions that matter
· Why it matters
chmod unix access-control
A 403 from nginx is often a filesystem problem, not a config problem. This post shows how to check which user nginx runs as and which bits it needs on every directory in the path.
403 on a static site that worked locally — the files came from /home/deploy and nginx says forbidden for every URL
An nginx 403 may involve mode bits, but this route cannot identify its cause. The calculator has no nginx integration, logs, configuration parser, process lookup or path walker. It answers narrower questions: whether a directory class has execute and whether a regular-file class has read, helping interpret evidence collected elsewhere.
Start with exact modes observed on each path component rather than assuming defaults. Enter each mode and choose its target type. Symbolic text, checkboxes and prose expose class permissions and confirm conversion, but cannot show that nginx attempted access, which identity it used or whether filesystem permissions produced the response.
A 403 may involve mode bits, but this route cannot identify its cause
The calculator cannot discover an nginx worker identity. It models owner, group and other classes, but no usernames, processes or memberships. A mode such as rwxr-xr-x therefore says nothing about whether a worker owns the object, belongs to its group or falls under other. External inspection must establish that classification.
Identity discovery must precede claims about relevant bits. Once evidence establishes the applicable class, the matrix shows read as 4, write as 2 and execute as 1. Before then, editing group or other is guesswork. The route reads no process state; it translates supplied modes rather than inferring server architecture.
The calculator does not discover an nginx worker identity
Inspect each directory component as a separate supplied mode. For directories, execute allows entry and name-based access, read allows listing, and write allows creating, renaming and deleting entries. The target-specific explanation helps reviewers determine whether the externally established class has execute on a particular component without claiming to inspect the path itself.
The browser does not walk from root to web root. It cannot locate a blocking component, confirm existence or inspect ACLs. Supply every observed directory mode separately, then check the final object as a regular file, where read concerns contents rather than listings. This interprets collected evidence instead of replacing filesystem inspection.
Files need r, and nothing more — why 644 is enough for static files and why 755 on files is not the fix
For a static file, 644 renders rw-r--r--. The owner receives read and write, while group and other receive read; nobody receives execute. This conversion shows that file read and execute are separate bits. The page has no basis for deciding whether a particular server needs execute, because server policy is absent.
Keep file and directory explanations distinct. Directory execute means entry and name-based reachability, while regular-file execute means running a program. The same checkbox therefore has target-specific prose. Comparing 644 with 755 clarifies bits, but cannot diagnose a 403 or prescribe a universal mode without configuration, identity, ACL and policy context.
Worked example: tracing /home/deploy/site/index.html — namei -l on the path and the ls -l line that reveals the blocker
A supported example begins after path evidence is gathered elsewhere. Suppose directory components are 755 and the final file is 644. The calculator renders directories as rwxr-xr-x, explaining group and other execute as entry and reachability. It renders the file as rw-r--r--, explaining group and other read as content access.
If a component is 750, its other triple is ---, while group remains r-x. That difference may matter, but does not prove nginx uses other. The route cannot run namei or ls, so external evidence must supply paths and modes. It then synchronizes every representation to reduce transcription errors during review.
Worked example: inspect supplied modes for each component of a path
Ownership decisions remain outside mode conversion. The panel reads no owner or group and offers no chown or chgrp operation. It cannot choose between deployment, service or shared-group ownership, nor assess moving content. Those decisions require system and workload evidence absent from the sources; no generated mode can replace that context.
Once ownership is resolved elsewhere, compare how modes divide access. Mode 750 gives full owner permissions, group read and execute, and nothing to other; 755 adds other read and execute. This remains conditional on knowing the worker's class. The inert command preview neither changes ownership nor confirms server access.
Ownership choices remain external to mode conversion
Configuration, index selection, mandatory access control and upstream behavior are not diagnosed here. No source loads nginx configuration, checks a URI or index, reads logs, contacts an upstream, or observes SELinux or AppArmor. Correctly converting a supplied mode therefore cannot establish why nginx returned 403; server evidence must answer that question.
Preserve this distinction when a mode appears suspicious. The panel may show that a directory class lacks execute or a file class lacks read, but relevance depends on identity and path evidence. Permissive bits also cannot exclude other causes. State exactly what the mode allows, then return to server-specific diagnostics.
Configuration, index, MAC and upstream causes are not diagnosed
Path access may depend on every component, yet the calculator sees one supplied value at a time. Its strength is accurate decoding: octal, symbolic text and checkboxes stay synchronized, while directory prose distinguishes listing, modification and entry. It simplifies review without pretending to discover either components or the process attempting access.
Establish the server identity and collect path modes outside this route. Decode every directory as a directory and the final object as a regular file, focusing on the externally verified class. Investigate configuration, ACLs and mandatory policy separately. The calculator validates arithmetic, but cannot identify a 403's cause or verify a fix.