Title: Nginx Configuration Essentials — LearnCoachAssist

Q: What does nginx stand for?
A: engine x — a high-performance open-source HTTP server, reverse proxy, and IMAP/POP3 mail proxy originally written by Igor Sysoev and first released in 2004.

Q: What is nginx's primary process model?
A: A single master process that reads configuration, manages sockets, and spawns worker processes (default count = CPU cores). Workers handle all incoming connections using an event-driven, non-blocking loop.

Q: How do you reload nginx configuration without dropping connections?
A: Send SIGHUP to the master process (or run nginx -s reload). The master re-reads config, spawns new workers with the new config, and gracefully shuts down old workers after their connections drain.

Q: What is the difference between nginx -s stop and nginx -s quit?
A: stop sends SIGTERM to workers and forces them to exit immediately, closing open connections. quit sends SIGQUIT, which lets workers finish serving current requests before exiting.

Q: What command tests configuration syntax without applying it?
A: nginx -t (or nginx -T to additionally dump the parsed configuration to stdout). Useful in CI/CD pipelines before a reload.

Q: Where is nginx's main configuration file by default on Linux?
A: /etc/nginx/nginx.conf. Additional files are typically included via include /etc/nginx/conf.d/*.conf; and per-site configs in /etc/nginx/sites-enabled/.

Q: What directive tells nginx to include another configuration file?
A: include /path/to/file.conf; Glob patterns are supported, e.g. include /etc/nginx/conf.d/*.conf;.

Q: What are the two main configuration contexts in nginx?
A: http {} (HTTP server settings) and server {} (virtual host). Inside them live location {}, upstream {}, events {}, and the top-level main context.

Q: What does the worker_processes directive control?
A: The number of worker processes the master spawns. The conventional setting is worker_processes auto;, which detects the number of CPU cores.

Q: What is the recommended value for worker_connections?
A: A practical starting point is worker_connections 1024; (or higher, e.g. 4096/8192) inside the events {} block. Max clients ≈ worker_processes × worker_connections.

Q: Which directive enables sendfile(2) for static file delivery?
A: sendfile on; inside http {} or server {}. It lets nginx use the kernel zero-copy path, dramatically speeding up static transfers.

Q: What does tcp_nopush do?
A: When enabled with sendfile, it instructs nginx to send response headers in one TCP packet (uses TCP_CORK). It is set with tcp_nopush on;.

Q: What does tcp_nodelay do?
A: Disables Nagle's algorithm (TCP_NODELAY) so small packets are sent immediately. With keepalive_timeout it enables the TCP_CORK / TCP_NODELAY trick for efficient keep-alive responses.

Q: What is the difference between alias and root in a location block?
A: root appends the request URI to the configured path. alias replaces the matched location prefix with the alias path. With root /var/www; and request /img/x.png nginx serves /var/www/img/x.png. With alias /var/www/; for the same request it serves /var/www/img/x.png — note alias requires a trailing slash matching the location.

Q: What is the server_name directive used for?
A: Defines virtual host names that a server block responds to. Supports exact names, leading wildcards (*.example.com), trailing wildcards (www.example.*), and regexes prefixed with ~.

Q: What is a default_server?
A: A server block marked with listen 80 default_server;. It handles requests whose Host header does not match any other server_name on that listen socket.

Q: What does the location directive match against?
A: Against the normalized request URI (after decoding and stripping ..). It supports prefix strings, exact match (=), preferential prefix (^~), and case-sensitive regex (~) or case-insensitive regex (~*).

Q: Order the location matching types from highest to lowest priority.
A: 1. = exact match → 2. ^~ preferential prefix → 3. ~/~* regex (first defined wins) → 4. longest matching prefix.

Q: What is the purpose of the try_files directive?
A: Checks files in order and serves the first that exists. Example: try_files $uri $uri/ /index.php?$query_string; — the last argument is a fallback URI or named location used when none exist.

Q: What does return do inside a location?
A: Sends an immediate HTTP response without contacting upstream. Example: return 301 https://example.com$request_uri; for a redirect, or return 404; to abort with Not Found.

Q: How do you perform a temporary vs permanent redirect in nginx?
A: Temporary: return 302 https://example.com$request_uri; Permanent: return 301 https://example.com$request_uri;. Use 301 only when the redirect is truly permanent (browsers cache aggressively).

Q: What is a named location (the @ prefix)?
A: A location starting with @ is only reachable via an internal redirect (e.g. try_files / @fallback; or error_page 404 @fallback;). It is used for request-handling logic independent of any URI.

Q: What does the rewrite directive do?
A: Rewrites the request URI using a regex, optionally capturing groups. Example: rewrite ^/old/(.*)$ /new/$1 permanent;. The last flag (last, break, redirect, permanent) controls whether further rewrite/location processing happens.

Q: What is the difference between rewrite ... last and rewrite ... break?
A: last stops the current server/location processing and starts a fresh match against the rewritten URI. break stops rewrite processing in the current location and continues with the rewritten URI in the same location.

Q: What is the classic Nginx + PHP-FPM configuration snippet?
A: location ~ \.php$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

Q: What is an upstream block?
A: Defines a named group of backend servers for proxying. Example: upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; keepalive 32; } Referenced as proxy_pass http://backend;.

Q: What load-balancing methods does nginx support out of the box?
A: Round-robin (default), least_conn, ip_hash, and random (with optional two method). Sticky sessions via ip_hash (or the newer sticky cookie|route|learn directive in nginx Plus).

Q: What does ip_hash do, and what is its limitation?
A: Hashes the client's IP to pick a backend so the same client always reaches the same server. Limitation: it cannot tell clients behind a shared NAT or proxy apart, and it breaks when a backend is added or removed (most clients remap).

Q: What does proxy_pass http://backend do (without a trailing slash)?
A: Forwards the full original URI to the upstream, including the matched location prefix. E.g. location /api/ with proxy_pass http://backend forwards /api/users as /api/users.

Q: What does proxy_pass http://backend/ do (with a trailing slash)?
A: Replaces the matched location prefix with /. E.g. location /api/ with proxy_pass http://backend/ forwards /api/users as /users.

Q: What does proxy_set_header Host $host do?
A: Sends the original Host header (or the server name) to the upstream. Without it, upstreams receive Host: backend (the upstream name), which can break virtual-hosted apps.

Q: How do you forward the real client IP and protocol to upstream?
A: proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;

Q: What is the difference between proxy_pass and fastcgi_pass?
A: proxy_pass forwards HTTP to another HTTP server. fastcgi_pass speaks the FastCGI protocol to PHP-FPM and similar apps, requiring fastcgi_param mappings instead of proxy_set_header.

Q: What is the uwsgi_pass directive used for?
A: Proxies to a uWSGI application server (commonly Python WSGI apps) using the uwsgi protocol on a TCP port or Unix socket.

Q: What is the grpc_pass directive?
A: Routes gRPC requests to a backend, e.g. location /helloworld.Greeter/ { grpc_pass grpc://backend; }. Requires HTTP/2 (TLS or cleartext h2c) and was introduced as stable in nginx 1.13.10.

Q: What does proxy_buffering on do?
A: When enabled, nginx buffers the entire upstream response to disk before forwarding to the client (great for slow clients, frees up upstream quickly). When off, responses stream straight through with minimum buffering.

Q: What is proxy_connect_timeout?
A: Time allowed to establish a TCP connection to the upstream. Default is 60s. Example: proxy_connect_timeout 5s;

Q: What is proxy_read_timeout?
A: Time allowed between two successive read operations from the upstream while a response is being received. Default 60s. Increase for slow long-poll/SSE endpoints.

Q: What is proxy_send_timeout?
A: Time allowed for transmitting a request to the upstream. Default 60s.

Q: What is client_max_body_size?
A: Limits the size of a client request body. Default is 1m. Raise it (e.g. client_max_body_size 50m;) to allow large file uploads; otherwise nginx returns 413 Request Entity Too Large.

Q: What does client_body_buffer_size control?
A: The buffer size for reading the request body. Requests exceeding it spill to a temporary file (client_body_temp_path). Default is 8k; common values are 16k/32k.

Q: How do you serve a directory listing?
A: Add autoindex on; inside the location (and ensure no index file exists). autoindex_exact_size off; shows sizes in KB/MB; autoindex_format html; is the default output style.

Q: What is the default index file list?
A: index index.html; by default — nginx serves index.html when a directory is requested. You can extend it: index index.html index.htm index.php;

Q: What does root /var/www/example.com; do at the server level?
A: Sets the document root for all locations in that server. Equivalent to placing root in each location. location-level root or alias overrides it.

Q: What is gzip on; used for?
A: Enables on-the-fly gzip compression of HTTP responses. Pair with gzip_types text/plain text/css application/json application/javascript text/xml; and gzip_min_length 256; to avoid compressing tiny responses.

Q: How do you enable gzip compression for a response that is not on the default MIME list?
A: Add the MIME type to gzip_types, e.g. gzip_types application/graphql+json application/xml;

Q: What is gzip_vary on; for?
A: Adds Vary: Accept-Encoding to responses so caches serve different gzip vs identity variants to different clients.

Q: What does the expires directive do?
A: Sets Cache-Control and Expires response headers. Example: expires 30d; for static assets. Use expires -1; to force Cache-Control: no-cache.

Q: How do you set far-future caching for fingerprinted assets?
A: location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 1y; add_header Cache-Control "public, immutable"; }

Q: How do you disable caching for HTML?
A: location ~* \.html$ { add_header Cache-Control "no-store, no-cache, must-revalidate"; expires off; }

Q: What does add_header do?
A: Adds an arbitrary response header, e.g. add_header X-Frame-Options "SAMEORIGIN";. Always add always when the response code is an error: add_header ... always;

Q: How do you enable HTTP/2 in nginx?
A: listen 443 ssl http2; — append http2 to the listen directive. Requires TLS. (Pre-nginx 1.25.1 used the separate http2 on; directive.)

Q: What are the minimum directives to enable TLS on a server block?
A: listen 443 ssl; ssl_certificate /etc/ssl/certs/example.com.pem; ssl_certificate_key /etc/ssl/private/example.com.key; ssl_protocols TLSv1.2 TLSv1.3;

Q: Which TLS protocols should you disable?
A: SSLv2, SSLv3, TLSv1.0, and TLSv1.1 are all deprecated. Use ssl_protocols TLSv1.2 TLSv1.3;

Q: What is the purpose of ssl_session_cache?
A: Stores TLS session parameters to skip the handshake on resumed connections. Recommended: ssl_session_cache shared:SSL:10m; (about 40 000 sessions per 1 MB).

Q: What does ssl_session_timeout set?
A: How long a cached TLS session is reusable. Default is 5m. Common values: 1d for browsers, 4h for APIs.

Q: How do you redirect all HTTP traffic to HTTPS?
A: server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; }

Q: What is HSTS and how do you enable it?
A: HTTP Strict Transport Security tells browsers to use HTTPS only. Enable with add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; on the HTTPS server.

Q: What does includeSubDomains in HSTS cover?
A: Extends the HSTS policy to every subdomain of the current host. Use carefully — a forgotten subdomain without HTTPS becomes unreachable.

Q: What is preload in the HSTS header?
A: Marks the site for inclusion in browsers' built-in HSTS preload list. Requires a submission to hstspreload.org and is hard to undo — browsers bake the policy in for months.

Q: What is OCSP stapling and how do you enable it?
A: Tells nginx to fetch OCSP responses from the CA and staple them into the TLS handshake. Enable with ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 1.1.1.1 valid=300s;

Q: How do you harden SSL/TLS ciphers?
A: ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; with ssl_prefer_server_ciphers on;

Q: What is ssl_prefer_server_ciphers on;?
A: Makes the server's cipher order win over the client's preference. Recommended for consistent hardening.

Q: What does ssl_dhparam do?
A: Loads Diffie-Hellman parameters for DHE ciphersuites. With modern ECDHE-only configurations this is no longer required; if used, generate at least 2048 bits: openssl dhparam -out dhparam.pem 4096

Q: How do you issue a Let's Encrypt certificate with the HTTP-01 challenge?
A: Run certbot --nginx -d example.com -d www.example.com, which edits the nginx config to add the /.well-known/acme-challenge/ location, obtains the cert, and updates the HTTPS block.

Q: What is the standard Let's Encrypt renewal hook for nginx?
A: certbot renew --quiet --deploy-hook "systemctl reload nginx" in a daily cron. Certificates expire every 90 days.

Q: How do you reload nginx after a certificate change?
A: nginx -s reload (or systemctl reload nginx). The master re-reads config and rotates workers, picking up the new certificate files without dropping connections.

Q: What is an access_log directive?
A: Specifies the log file, format, and buffer. Example: access_log /var/log/nginx/access.log combined;. To disable, use access_log off;.

Q: What is the meaning of the combined log format?
A: The default access log format: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"

Q: How do you define a custom log format?
A: log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt=$request_time uct=$upstream_connect_time uht=$upstream_header_time urt=$upstream_response_time'; then reference it by name.

Q: What does $request_time measure?
A: Total time spent processing the request in seconds, from the first byte received from the client to the last byte sent back. Useful for end-to-end latency reporting.

Q: What does $upstream_response_time measure?
A: Time spent receiving the response from the upstream, in seconds, with millisecond precision. Multiple values (comma-separated) are recorded when retries occur.

Q: What is open_log_file_cache used for?
A: Caches file descriptors and metadata for frequently written log files to reduce syscall overhead. Example: open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

Q: How do you disable buffering for access logs?
A: Add flush parameter or set buffer= to 0: access_log /var/log/nginx/access.log combined buffer=32k flush=5s;

Q: What does error_log capture?
A: Runtime errors and warnings. Default level is error. Increase verbosity with error_log /var/log/nginx/error.log info; or debug (which requires error_log ... debug; plus a debug build).

Q: How do you debug a request end-to-end?
A: Enable the debug log in the relevant context (error_log /var/log/nginx/error.log debug;) and use debug_connection 1.2.3.4; to limit the volume to a single client.

Q: What is the difference between allow and deny in nginx?
A: ACL directives for client access control. allow permits; deny rejects with 403. Example: allow 10.0.0.0/8; deny all;

Q: How do you protect a location with HTTP Basic Auth?
A: auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; Generate the file with htpasswd -c /etc/nginx/.htpasswd alice.

Q: What does limit_req_zone do?
A: Defines a shared memory zone that counts request rates per key (typically $binary_remote_addr). Example: limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

Q: How do you apply a rate limit to a location?
A: limit_req zone=one burst=20 nodelay; inside the location. burst is the queue size; nodelay serves queued requests immediately instead of spacing them.

Q: What is limit_conn for?
A: Limits the number of concurrent connections per key. Define a zone with limit_conn_zone $binary_remote_addr zone=addr:10m; and apply with limit_conn addr 10;

Q: What is the default value of keepalive_timeout?
A: 75s. Lower it (e.g. keepalive_timeout 30;) for high-volume servers to free worker sockets sooner.

Q: How do you support keep-alive connections to upstream backends?
A: Add keepalive 32; inside the upstream block and use proxy_http_version 1.1; proxy_set_header Connection ""; in the location to enable HTTP/1.1 keep-alive to the upstream pool.

Q: What does proxy_http_version 1.1; achieve?
A: Switches the upstream protocol to HTTP/1.1, which is required for keep-alive and for chunked transfer encoding to work cleanly with most modern apps.

Q: What is the purpose of proxy_set_header Connection "";?
A: Clears the Connection header sent to the upstream. Required when activating upstream keep-alive so the upstream does not see Connection: close.

Q: How do you hide the nginx version in error pages and Server headers?
A: Use server_tokens off;. It strips the version from error pages and from the Server response header.

Q: What does more_clear_headers do, and is it built-in?
A: It removes response headers set by upstream. It is not built into nginx OSS — it comes from the headers-more module. Equivalent built-in trick: set the header to an empty string: proxy_hide_header X-Powered-By;

Q: How do you strip X-Powered-By from upstream responses?
A: proxy_hide_header X-Powered-By; inside the relevant location or server.

Q: What does add_header X-Frame-Options "DENY" always; accomplish?
A: Clickjacking protection — tells browsers to disallow framing the page in an <iframe>. always ensures the header is added to error responses too.

Q: What is the standard set of security headers for a production site?
A: X-Frame-Options, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, Content-Security-Policy, and Permissions-Policy — all set with add_header ... always;

Q: What does X-Content-Type-Options: nosniff prevent?
A: Stops browsers from MIME-sniffing a response away from the declared Content-Type, mitigating some XSS / content-confusion attacks.

Q: How do you deny access to hidden files (e.g. .git, .env)?
A: location ~ /\. { deny all; return 404; }

Q: How do you rate-limit login attempts to a specific URL?
A: Combine limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m; with location = /login { limit_req zone=login burst=10 nodelay; ... }

Q: What is proxy_cache_path?
A: Defines a disk-based cache zone for proxy responses. Example: proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

Q: How do you enable proxy caching for a location?
A: proxy_cache my_cache; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; add_header X-Cache-Status $upstream_cache_status;

Q: What does the X-Cache-Status header indicate?
A: upstream_cache_status — HIT, MISS, BYPASS, EXPIRED, STALE, UPDATING, or REVALIDATED — for debugging cache behavior.

Q: How do you bypass the cache for a specific cookie or request?
A: proxy_cache_bypass $cookie_nocache $arg_nocache; proxy_no_cache $cookie_nocache $arg_nocache; This causes authenticated or tagged requests to skip the cache.

Q: What is the difference between proxy_cache_bypass and proxy_no_cache?
A: proxy_no_cache decides whether to save the response to cache at all. proxy_cache_bypass decides whether to serve the request from cache (if available) or fetch fresh — they are often used together for the same condition.

Q: What does fastcgi_cache_path do?
A: Same as proxy_cache_path but for FastCGI (typically PHP-FPM) responses. Pair with fastcgi_cache, fastcgi_cache_valid, and fastcgi_cache_key "$scheme$request_method$host$request_uri".

Q: What is a typical fastcgi_cache_key for a WordPress site?
A: fastcgi_cache_key "$scheme$request_method$host$request_uri" — optionally add $cookie_logged_in so authenticated users bypass the cache.

Q: What does the if directive do and what are its pitfalls?
A: if creates a conditional branch. The official wiki warns: if is evil when used outside location or when checking request headers — prefer map, try_files, or a dedicated location block.

Q: How do you safely check a header with if?
A: Use if ($http_x_custom = "yes") { ... } — variables prefixed with $http_ are safe. Avoid $http_user_agent for routing because user agents are untrusted and frequently lie.

Q: What is the map directive?
A: Builds a new variable by matching input against patterns, evaluated once per request. map $http_accept_language $lang { default en; ~^fr fr; } in the http context.

Q: What is the geo directive?
A: Creates a variable whose value depends on the client IP, loaded from a CIDR list. Used for geolocation, allow/deny lists, and routing: geo $country { default ZZ; 10.0.0.0/8 US; }

Q: How do you stream large responses (e.g. video) with nginx?
A: proxy_buffering off; proxy_cache off; add_header X-Accel-Buffering no; chunked_transfer_encoding on; This prevents nginx from holding the whole response in memory before forwarding.

Q: What is X-Accel-Redirect?
A: A response header from upstream that tells nginx to serve an internal file and finish the request. Example: X-Accel-Redirect: /protected/file.pdf maps to an internal location for access-controlled downloads.

Q: How do you mark a location as internal-only?
A: Add internal; inside the location block. Requests from clients return 404; only internal redirects (X-Accel-Redirect, error_page, rewrite ... last) can reach it.

Q: What does add_header X-Accel-Buffering no; do?
A: Disables nginx's response buffering for a particular request so it streams straight to the client — useful for Server-Sent Events and long-polling.

Q: What is resolver used for?
A: Names the DNS server(s) nginx uses to resolve upstream hostnames (e.g. resolver 1.1.1.1 8.8.8.8 valid=300s;). Required for variables like proxy_pass http://my.service.consul:$server_port;.

Q: How do you configure nginx for websockets?
A: proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; — these four lines forward the WebSocket handshake and keep the connection open.

Q: What does proxy_read_timeout 86400; do for websockets?
A: Allows the upstream connection to stay idle for 24 hours instead of timing out at 60 s, so long-lived socket sessions are not dropped.

Q: How do you serve a SPA (React/Vue) with history-mode routing?
A: location / { try_files $uri $uri/ /index.html; } — falls back to index.html for any path that isn't a static file, letting the client router take over.

Q: What is the canonical "Nginx + Vue/React history fallback" snippet?
A: location / { root /var/www/app/dist; try_files $uri $uri/ /index.html; } location ~* \.(?:js|css|woff2?|png|jpg|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; }

Q: How do you enable gzip pre-compressed .gz files?
A: gzip_static on; nginx serves the pre-compressed version of file.js when file.js.gz exists, saving CPU at request time.

Q: How do you enable Brotli compression?
A: Requires the nginx-module-brotli (or built-in via Cloudflare/QuicTLS forks). Then brotli on; brotli_types text/plain text/css application/javascript application/json; brotli_comp_level 6;

Q: What is the server directive inside upstream?
A: Defines one backend. server backend1.example.com:8080 weight=3 max_fails=3 fail_timeout=30s;. weight biases load balancing; max_fails + fail_timeout mark a server as down after repeated errors.

Q: What is the backup parameter on an upstream server?
A: server 10.0.0.99:8080 backup; — this server is only used when all primary servers are down. Useful for a cold standby.

Q: How do you mark an upstream server as permanently down for maintenance?
A: server 10.0.0.5:8080 down; — nginx skips it entirely without removing the entry.

Q: What does max_fails=0 mean?
A: Disables health checking for that server — it is always considered available, even after errors. Use only for backends with their own reliability guarantees.

Q: What is proxy_next_upstream?
A: Specifies which error conditions cause nginx to retry the next upstream. Example: proxy_next_upstream error timeout http_502 http_503 http_504;. Avoid including http_404 unless intentional.