Operations 7 min read

Why Nginx Returned 403 After Jenkins Deployment and How to Fix It

This article walks through a real‑world deployment failure where Nginx served a 403 error after Jenkins‑driven releases, explains the root causes such as file‑permission mismatches and Tomcat 8's default umask, and provides step‑by‑step fixes to restore proper access.

Efficient Ops
Efficient Ops
Efficient Ops
Why Nginx Returned 403 After Jenkins Deployment and How to Fix It

Background

The release system consists of Jenkins invoking a deployment program (code‑named varian ) that builds a Docker image, pushes it to a registry, and updates a container cluster accessed through a load balancer.

The legacy varian was a mix of shell and Python scripts running on Jenkins (JDK 1.7) with many compatibility hacks, resulting in tangled code.

We decided to rewrite varian entirely in Python, modularize its functions, upgrade Jenkins to the latest version, and move JDK to 1.8. The new environment runs on Debian 8 with Python 3.4, JDK 1.8, and Jenkins 2.134.

System: Debian 8

Language: Python 3.4

JDK 1.8 + Jenkins 2.134

Fault Handling Process

Resolving Nginx 403 Errors

After Jenkins deployed a static HTML project, the web page loaded without CSS because the browser reported a 403 status for the CSS file.

Typical reasons for Nginx returning 403 include:

IP not in the configured whitelist.

Directory listing disabled while the request points to a directory.

File owned by a user/group that Nginx lacks read permission for.

Incorrect index directive (e.g., referencing index.shtml when only index.html exists).

Investigation showed the CSS file owned by root:root with permissions -rw-r-----, while Nginx runs as www-data. The missing read permission for the www-data user caused the 403.

Understanding Linux File Permissions

Example output: -rw-r----- 1 root root 7.9K Jul 24 12:34 csl.css The first ten characters define the file type and permission bits.

Characters 2‑4: owner permissions; 5‑7: group permissions; 8‑10: others.

Permissions are represented by r (read = 4), w (write = 2), x (execute = 1).

In the example, the owner has read/write, the group has read, others have none.

Tomcat 8 UMASK Issue

Running the same Python script directly from the console produced correct file permissions, but executing it via Jenkins resulted in wrong permissions.

The discrepancy was due to the umask setting, which defines default permissions for newly created files. While both the root and Jenkins users had a umask of 0022, Tomcat 8 (the container running Jenkins) changed the default umask to 0027, stripping group read/write bits.

Changing Tomcat 8’s umask back to 0022 resolved the permission problem.

Article originally published by the “运维咖啡吧” public account, author “37丫37”.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DeploymentLinux permissionsumask403
Efficient Ops
Written by

Efficient Ops

This public account is maintained by Xiaotianguo and friends, regularly publishing widely-read original technical articles. We focus on operations transformation and accompany you throughout your operations career, growing together happily.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.