{"id":887,"date":"2026-09-22T12:17:53","date_gmt":"2026-09-22T12:17:53","guid":{"rendered":"https:\/\/www.vps.tc\/blog\/?p=887"},"modified":"2026-09-22T09:50:04","modified_gmt":"2026-09-22T09:50:04","slug":"install-configure-nginx-on-ubuntu","status":"publish","type":"post","link":"https:\/\/www.vps.tc\/blog\/en\/install-configure-nginx-on-ubuntu\/","title":{"rendered":"How to Install and Configure Nginx on Ubuntu"},"content":{"rendered":"<div class=\"aiw-summary\" id=\"aiw-ozet\">\n<p class=\"aiw-summary-title\">Quick Summary &#8211; Installing Nginx on Ubuntu<\/p>\n<p>Install the package, verify the service, and handle network access, DNS, and the domain configuration as separate checks. That way, a failed request gives you a smaller problem to investigate.<\/p>\n<ul>\n<li><strong>Install the package<\/strong> \u2014 Refresh the APT index and install Nginx with sudo apt install nginx.<\/li>\n<li><strong>Check the service<\/strong> \u2014 Use systemctl and curl to confirm that Nginx is running and answering locally.<\/li>\n<li><strong>Open required ports<\/strong> \u2014 Allow TCP 80 and 443 in UFW and check any provider-level firewall separately.<\/li>\n<li><strong>Create a server block<\/strong> \u2014 Define the domain, document root, logs, and request handling in sites-available.<\/li>\n<li><strong>Verify DNS<\/strong> \u2014 Use dig +short to compare A and AAAA records with the server&#039;s public addresses.<\/li>\n<li><strong>Test before reload<\/strong> \u2014 Run nginx -t and inspect logs before reloading or restarting the service.<\/li>\n<\/ul>\n<\/div>\n<p class=\"aiw-lead\">Install Nginx with APT, verify its local response, open the required firewall ports, and configure a server block for your domain. Check DNS and each network layer separately, then add HTTPS after HTTP works; the first failed check will usually tell you where to look.<\/p>\n<div class=\"aiw-toc\" style=\"border:1px solid #dbe3ea;border-radius:8px;padding:16px 20px;margin:0 0 28px\">\n<p class=\"aiw-toc-head\"><strong>Table of Contents<\/strong><span class=\"aiw-toc-meta\"> \u00b7 13 min read<\/span><\/p>\n<ol style=\"margin:10px 0 0;padding-left:22px\">\n<li><a href=\"#what-should-you-prepare-before-installing-nginx-on-ubuntu\">What should you prepare before installing Nginx on Ubuntu?<\/a><\/li>\n<li><a href=\"#how-do-you-install-nginx-on-ubuntu\">How do you install Nginx on Ubuntu?<\/a><\/li>\n<li><a href=\"#how-do-you-open-http-and-https-ports-with-ufw\">How do you open HTTP and HTTPS ports with UFW?<\/a><\/li>\n<li><a href=\"#where-are-the-nginx-configuration-files\">Where are the Nginx configuration files?<\/a><\/li>\n<li><a href=\"#how-do-you-create-a-server-block-for-a-domain\">How do you create a server block for a domain?<\/a><\/li>\n<li><a href=\"#how-do-you-point-dns-at-nginx\">How do you point DNS at Nginx?<\/a><\/li>\n<li><a href=\"#how-do-you-test-and-troubleshoot-nginx\">How do you test and troubleshoot Nginx?<\/a><\/li>\n<li><a href=\"#when-should-you-add-https\">When should you add HTTPS?<\/a><\/li>\n<li><a href=\"#which-permissions-and-maintenance-settings-matter\">Which permissions and maintenance settings matter?<\/a><\/li>\n<li><a href=\"#how-i-verify-an-nginx-change-before-touching-a-customer-server\">How I verify an Nginx change before touching a customer server<\/a><\/li>\n<li><a href=\"#check-these-before-you-put-the-site-online\">Check These Before You Put the Site Online<\/a><\/li>\n<li><a href=\"#frequently-asked-questions\">Frequently Asked Questions<\/a><\/li>\n<li><a href=\"#sources\">Sources<\/a><\/li>\n<\/ol>\n<\/div>\n<h2 id=\"what-should-you-prepare-before-installing-nginx-on-ubuntu\">What should you prepare before installing Nginx on Ubuntu?<\/h2>\n<p>When I install Nginx on a fresh Ubuntu VPS, I do not start by editing a server block. I first make sure the package manager works, the service can answer locally, and I can still reach the machine over SSH. That order has saved me from mixing a firewall problem with a configuration problem more than once.<\/p>\n<p>The sequence is simple: install Nginx, verify it, open the required ports, configure the domain, test DNS, and add HTTPS after HTTP works. Each step gives you a smaller problem to investigate if something fails.<\/p>\n<h2 id=\"how-do-you-install-nginx-on-ubuntu\">How do you install Nginx on Ubuntu?<\/h2>\n<p>The commands below apply to Ubuntu 22.04 and 24.04 with a user that has <code>sudo<\/code> access. I prefer using <code>sudo<\/code> for individual commands instead of keeping a root shell open. It limits the reach of an accidental command, which matters on a VPS.<\/p>\n<pre><code>sudo apt update\nsudo apt install nginx<\/code><\/pre>\n<p><code>apt update<\/code> refreshes the package indexes; it does not upgrade packages by itself. <code>apt install nginx<\/code> installs Nginx and its dependencies. Ubuntu will usually start the service during installation, but I do not treat that as a guarantee. Check it.<\/p>\n<pre><code>sudo systemctl enable --now nginx\nsudo systemctl status nginx --no-pager<\/code><\/pre>\n<p><code>enable --now<\/code> enables Nginx at boot and starts it immediately. The status output should include <code>Active: active (running)<\/code>. Test a local HTTP response as well.<\/p>\n<pre><code>curl -I http:\/\/127.0.0.1<\/code><\/pre>\n<p>A normal installation returns <code>200 OK<\/code>, although another successful status may appear if a redirect has already been configured. If Ubuntu&#8217;s default Nginx page opens in a browser, the service is working at a basic level. Your domain and application configuration are still separate tasks.<\/p>\n<p><strong>Verify the installation<\/strong> &#8211; Do not move on to virtual host configuration until <code>systemctl<\/code> and <code>curl<\/code> both show that the service is responding.<\/p>\n<h2 id=\"how-do-you-open-http-and-https-ports-with-ufw\">How do you open HTTP and HTTPS ports with UFW?<\/h2>\n<p>An internet-facing web server normally uses TCP 80 for HTTP and TCP 443 for HTTPS. If UFW is enabled, allow those ports. Before changing firewall rules over SSH, confirm that your current SSH port is allowed. Otherwise, you can create an access outage that has nothing to do with Nginx.<\/p>\n<pre><code>sudo ufw status verbose\nsudo ufw allow 'Nginx Full'\nsudo ufw status numbered<\/code><\/pre>\n<p>The <code>Nginx Full<\/code> profile allows TCP 80 and 443. For a temporary HTTP-only test machine, <code>sudo ufw allow 'Nginx HTTP'<\/code> is enough. If UFW is inactive, these commands add rules but do not filter traffic. A cloud security group or the VPS provider&#8217;s network firewall must be checked separately.<\/p>\n<p>I once assumed a host firewall change had failed because the site was still unreachable. The UFW output was fine; the provider-level firewall was blocking the port. The lesson was not clever: check both firewalls before changing Nginx.<\/p>\n<pre><code>sudo ss -ltnp | grep -E ':(80|443)\\s'<\/code><\/pre>\n<p>This shows which TCP ports are listening at the operating-system level. The output may show Nginx listening on <code>0.0.0.0:80<\/code> or <code>[::]:80<\/code>. If you only see <code>127.0.0.1:80<\/code>, the service may not be accepting external connections. Inspect the relevant <code>listen<\/code> directive and the active configuration.<\/p>\n<p><strong>Keep the firewall narrow<\/strong> &#8211; Allow only the TCP ports you actually need, commonly 22, 80, and 443. If SSH uses a different port, adjust the rule to match it.<\/p>\n<div class=\"aiw-callout aiw-callout-warn\">\n<p class=\"aiw-callout-label\">Caution<\/p>\n<p>UFW rules do not replace a cloud provider security group. If the VPS panel blocks TCP 80 or 443, changing UFW on the server will not make the site reachable.<\/p>\n<\/div>\n<h2 id=\"where-are-the-nginx-configuration-files\">Where are the Nginx configuration files?<\/h2>\n<p>The Ubuntu package separates Nginx configuration into several directories. The main file is <code>\/etc\/nginx\/nginx.conf<\/code>, while site definitions usually live in <code>\/etc\/nginx\/sites-available\/<\/code>. Active sites are selected through symbolic links in <code>\/etc\/nginx\/sites-enabled\/<\/code>.<\/p>\n<table>\n<thead>\n<tr>\n<th>Path<\/th>\n<th>Purpose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>\/etc\/nginx\/nginx.conf<\/code><\/td>\n<td>Global settings and included configuration files<\/td>\n<\/tr>\n<tr>\n<td><code>\/etc\/nginx\/sites-available\/<\/code><\/td>\n<td>Prepared or inactive site configurations<\/td>\n<\/tr>\n<tr>\n<td><code>\/etc\/nginx\/sites-enabled\/<\/code><\/td>\n<td>Symbolic links for active server blocks<\/td>\n<\/tr>\n<tr>\n<td><code>\/var\/www\/html<\/code><\/td>\n<td>Ubuntu&#8217;s default site document root<\/td>\n<\/tr>\n<tr>\n<td><code>\/var\/log\/nginx\/<\/code><\/td>\n<td>Access and error log files<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Using a symbolic link instead of copying a site file makes administration easier. To disable a site, remove the link while keeping the original configuration available for later use.<\/p>\n<pre><code>sudo ls -la \/etc\/nginx\/sites-enabled\/\nsudo ls -la \/etc\/nginx\/sites-available\/<\/code><\/pre>\n<p>The default Ubuntu site usually has the name <code>default<\/code>. Before configuring a domain, check whether it is catching requests intended for your own server block. When several server blocks exist, Nginx considers the requested address, port, and <code>Host<\/code> header.<\/p>\n<h2 id=\"how-do-you-create-a-server-block-for-a-domain\">How do you create a server block for a domain?<\/h2>\n<p>Nginx&#8217;s equivalent of an Apache virtual host is called a <code>server block<\/code>. In this example, the domain is <code>example.com<\/code> and the document root is <code>\/var\/www\/example.com\/public<\/code>. Create the directory first, then place a file there that Nginx can read.<\/p>\n<pre><code>sudo mkdir -p \/var\/www\/example.com\/public\nsudo chown -R \"$USER\":\"$USER\" \/var\/www\/example.com\nsudo find \/var\/www\/example.com -type d -exec chmod 755 {} +\nsudo find \/var\/www\/example.com -type f -exec chmod 644 {} +\nprintf '%s\\n' '&lt;!doctype html&gt;&lt;html lang=\"en\"&gt;&lt;body&gt;&lt;h1&gt;Nginx is working&lt;\/h1&gt;&lt;\/body&gt;&lt;\/html&gt;' | tee \/var\/www\/example.com\/public\/index.html<\/code><\/pre>\n<p>The separate directory and file permissions avoid making every file executable. In production, choose ownership according to the application&#8217;s deployment model. Giving everything to <code>www-data<\/code> is not automatically correct: the deployment account may need write access, while Nginx may only need read and directory-traversal permissions.<\/p>\n<p>Now create the server block:<\/p>\n<pre><code>sudo vim \/etc\/nginx\/sites-available\/example.com<\/code><\/pre>\n<pre><code>server {\n    listen 80;\n    listen [::]:80;\n\n    server_name example.com www.example.com;\n    root \/var\/www\/example.com\/public;\n    index index.html index.htm;\n\n    access_log \/var\/log\/nginx\/example.com.access.log;\n    error_log  \/var\/log\/nginx\/example.com.error.log;\n\n    location \/ {\n        try_files $uri $uri\/ =404;\n    }\n}<\/code><\/pre>\n<p><code>server_name<\/code> defines the domain match, <code>root<\/code> defines where files are looked up, and <code>index<\/code> lists the files to try for a directory request. <code>try_files<\/code> serves an existing file and returns <code>404<\/code> when no matching file exists. A PHP, Node.js, or other application normally needs different proxy or FastCGI settings.<\/p>\n<p>Enable the site and disable the default site if you no longer need it:<\/p>\n<pre><code>sudo ln -s \/etc\/nginx\/sites-available\/example.com \/etc\/nginx\/sites-enabled\/example.com\nsudo rm -f \/etc\/nginx\/sites-enabled\/default\nsudo nginx -t\nsudo systemctl reload nginx<\/code><\/pre>\n<p><code>nginx -t<\/code> checks the syntax and then verifies that the configuration can be loaded. You should see <code>syntax is ok<\/code> and <code>test is successful<\/code>. A <code>reload<\/code> applies the configuration without the interruption that an unnecessary <code>restart<\/code> can cause.<\/p>\n<p><strong>Enable the server block<\/strong> &#8211; Create the symbolic link, run <code>nginx -t<\/code>, and reload only after the test succeeds.<\/p>\n<div class=\"aiw-callout aiw-callout-tip\">\n<p class=\"aiw-callout-label\">Tip<\/p>\n<p>Use a symbolic link from sites-available to sites-enabled so disabling a site does not delete its configuration. Always test with nginx -t before a reload.<\/p>\n<\/div>\n<h2 id=\"how-do-you-point-dns-at-nginx\">How do you point DNS at Nginx?<\/h2>\n<p>For Nginx to answer the right domain, the domain&#8217;s DNS records must point to the server&#8217;s public IP address. Use an <code>A<\/code> record for IPv4 and an <code>AAAA<\/code> record for IPv6. The record in the DNS panel is only half of the setup; Nginx must also listen on that address.<\/p>\n<pre><code>dig +short A example.com\ndig +short AAAA example.com\ncurl -I -H 'Host: example.com' http:\/\/SERVER_IP<\/code><\/pre>\n<p>The first two commands show the addresses returned by DNS. The third sends a request to a specific server with the <code>Host<\/code> header, so you can test server-block selection without waiting for DNS caches to update. Replace <code>SERVER_IP<\/code> with the actual address.<\/p>\n<p>DNS changes become visible according to TTLs, resolver caches, and provider behavior. Seeing an old result in a browser does not automatically mean Nginx is misconfigured. If the name cannot be resolved at all, the existing post <em><a href=\"https:\/\/www.vps.tc\/blog\/en\/how-to-fix-dns-probe-finished-nxdomain-error\/\">How to Fix DNS_PROBE_FINISHED_NXDOMAIN Error<\/a><\/em> covers the DNS-side checks.<\/p>\n<p><strong>Check DNS from the terminal<\/strong> &#8211; Compare the output of <code>dig +short<\/code> for both A and AAAA records with the addresses assigned to your server instead of trusting the control panel alone.<\/p>\n<div class=\"aiw-callout aiw-callout-example\">\n<p class=\"aiw-callout-label\">Example<\/p>\n<p>You can test a server block before DNS has updated by sending a request to the server IP with curl -H &#039;Host: example.com&#039;. This checks Nginx routing without relying on a browser cache.<\/p>\n<\/div>\n<h2 id=\"how-do-you-test-and-troubleshoot-nginx\">How do you test and troubleshoot Nginx?<\/h2>\n<p>After any configuration change, start with <code>nginx -t<\/code>. If the command fails, do not reload; the running configuration remains in place. The file path and line number in the error message usually take you close to the problem.<\/p>\n<pre><code>sudo nginx -t\nsudo nginx -T | less<\/code><\/pre>\n<p><code>nginx -T<\/code> prints the complete configuration, including files loaded through <code>include<\/code> directives. Duplicate <code>server_name<\/code> values in different files can produce unexpected matches, and this combined output helps reveal them.<\/p>\n<p>If the service will not start or requests return errors, inspect the logs before restarting anything. A restart is not a diagnostic method.<\/p>\n<pre><code>sudo journalctl -u nginx -b --no-pager\nsudo tail -n 50 \/var\/log\/nginx\/error.log\nsudo tail -n 50 \/var\/log\/nginx\/example.com.error.log<\/code><\/pre>\n<p>Common causes include <code>permission denied<\/code>, an incorrect file path, a port conflict, and a missing certificate file. A <code>502 Bad Gateway<\/code> usually points to an upstream that is not listening or to incorrect Unix socket permissions. The post <em><a href=\"https:\/\/www.vps.tc\/blog\/en\/how-to-fix-502-bad-gateway-error\/\">How to Fix a 502 Bad Gateway Error<\/a><\/em> also covers those upstream checks.<\/p>\n<p><strong>Read the logs<\/strong> &#8211; Before restarting, inspect <code>journalctl<\/code>, the Nginx error log, and listening ports together. The first useful error is often already there.<\/p>\n<h2 id=\"when-should-you-add-https\">When should you add HTTPS?<\/h2>\n<p>Add HTTPS after you have confirmed that the domain works over HTTP. Before requesting a certificate, make sure DNS is correct and TCP ports 80 and 443 are reachable from outside. For Let&#8217;s Encrypt&#8217;s HTTP-01 challenge, port 80 is required by that validation method.<\/p>\n<p>For Certbot installation and certificate management on Ubuntu, follow the current official instructions for your distribution and web server. On the version I run, the usual next steps are to add a 443 listener, certificate paths, and an HTTP-to-HTTPS redirect to the Nginx server block. Test renewal with <code>certbot renew --dry-run<\/code>; a certificate issued once is not proof that renewal will work later.<\/p>\n<p>When Nginx sits behind a proxy, HTTPS redirects also depend on headers such as <code>X-Forwarded-Proto<\/code> being handled correctly. If the application thinks every HTTPS request is HTTP, it can produce a redirect loop. The post <em><a href=\"https:\/\/www.vps.tc\/blog\/en\/install-wordpress-on-vps-step-by-step\/\">How to Install WordPress on a VPS: Step-by-Step Guide<\/a><\/em> discusses the Nginx, PHP-FPM, and domain layers together.<\/p>\n<p><strong>Test renewal early<\/strong> &#8211; Confirm external access to the challenge path and run a dry renewal before the certificate is close to expiring.<\/p>\n<h2 id=\"which-permissions-and-maintenance-settings-matter\">Which permissions and maintenance settings matter?<\/h2>\n<p>Nginx needs directory-traversal permission on every parent directory and read permission on the files it serves. Giving everything <code>chmod 777<\/code> is not a fix; it hides the original permission problem by removing useful boundaries. Directories that an application must write to, such as uploads or cache directories, should be handled separately.<\/p>\n<p>Logs accumulate under <code>\/var\/log\/nginx\/<\/code>. The Ubuntu package includes logrotate integration, but you should still monitor disk usage and confirm that rotation behaves as expected.<\/p>\n<pre><code>sudo du -sh \/var\/log\/nginx\nsudo logrotate -d \/etc\/logrotate.d\/nginx\nsudo systemctl is-enabled nginx<\/code><\/pre>\n<p>The first command reports log size, the second simulates logrotate&#8217;s decisions, and the third shows whether Nginx is enabled at boot. Before updating Nginx, record the current configuration and application services so a rollback is easier.<\/p>\n<p>During an operating-system update, <code>apt<\/code> may ask how to handle a locally changed configuration file. Keeping site definitions and custom include files separate from the main package-managed file reduces that risk. Version-controlling configuration makes changes visible, but never commit private keys or other secrets to the repository.<\/p>\n<p><strong>Limit permissions<\/strong> &#8211; Keep Nginx read-only where possible, give write access only to application paths that need it, and inspect log rotation regularly.<\/p>\n<h2 id=\"how-i-verify-an-nginx-change-before-touching-a-customer-server\">How I verify an Nginx change before touching a customer server<\/h2>\n<p>I keep a Dell OptiPlex 7050 running Proxmox at home, and configuration changes get tested there before I use them on a customer VPS. My sequence is deliberately boring: check the hostname, inspect listening ports, run <code>nginx -t<\/code>, make a local request with <code>curl<\/code>, and only then reload.<\/p>\n<p>I once spent time investigating a supposedly broken server block that was simply not enabled. The file in <code>sites-available<\/code> looked perfect, but there was no matching symbolic link in <code>sites-enabled<\/code>. The configuration test passed. The request still reached the default site.<\/p>\n<p>That mistake changed how I check Nginx: a valid file is not necessarily an active configuration. Treat installation, firewall access, DNS resolution, server-block selection, and application connectivity as separate checks. The first failed layer is usually the one worth fixing.<\/p>\n<p>For package behavior and directive details, I check the <a href=\"https:\/\/nginx.org\/en\/docs\/\" target=\"_blank\" rel=\"noopener\">Nginx documentation<\/a>, the <a href=\"https:\/\/documentation.ubuntu.com\/server\/how-to\/web-services\/install-nginx\/\" target=\"_blank\" rel=\"noopener\">Ubuntu Server installation notes<\/a>, the <a href=\"https:\/\/ubuntu.com\/server\/docs\/firewalls\/\" target=\"_blank\" rel=\"noopener\">Ubuntu firewall documentation<\/a>, and the <a href=\"https:\/\/letsencrypt.org\/docs\/challenge-types\/\" target=\"_blank\" rel=\"noopener\">Let&#8217;s Encrypt challenge documentation<\/a>.<\/p>\n<div class=\"aiw-callout aiw-callout-field\">\n<p class=\"aiw-callout-label\">From the field<\/p>\n<p>I once had a valid site file sitting unused because I had forgotten the symbolic link in sites-enabled. The configuration test passed, but the request still reached the default site; checking active links saved more time than rewriting the server block.<\/p>\n<\/div>\n<h2 id=\"check-these-before-you-put-the-site-online\">Check These Before You Put the Site Online<\/h2>\n<ul class=\"aiw-checklist\">\n<li>Update the APT package index.<\/li>\n<li>Install Nginx and verify that the service is active.<\/li>\n<li>Confirm that SSH access remains allowed before changing UFW.<\/li>\n<li>Allow only the required HTTP and HTTPS ports.<\/li>\n<li>Create the document root with appropriate ownership and permissions.<\/li>\n<li>Create and enable the domain&#039;s server block.<\/li>\n<li>Run nginx -t before every reload and test certificate renewal with certbot renew &#8211;dry-run.<\/li>\n<\/ul>\n<div class=\"aiw-cta\">\n<p>If you are setting up a new VPS, keep the output from nginx -t and curl beside you while you work through the checks. I trust a change much more when I can say exactly which layer I tested.<\/p>\n<p class=\"aiw-cta-action\"><a href=\"https:\/\/www.vps.tc\/en\/vps\">Explore VPS plans<\/a><\/p>\n<\/div>\n<h2 id=\"frequently-asked-questions\">Frequently Asked Questions<\/h2>\n<div class=\"aiw-faq\">\n<details class=\"aiw-faq-item\" open>\n<summary>Can I install Nginx on Ubuntu without logging in as root?<\/summary>\n<p>Yes. Use a normal account with sudo privileges. Commands such as sudo apt install nginx, sudo systemctl reload nginx, and sudo nginx -t request elevated access only when needed. This is easier to audit than keeping a root shell open for the whole setup.<\/p>\n<\/details>\n<details class=\"aiw-faq-item\">\n<summary>Which ports must be open for an Nginx website?<\/summary>\n<p>TCP 80 is normally required for HTTP and for Let&#039;s Encrypt HTTP-01 validation. TCP 443 is required for HTTPS. You also need your SSH port open for administration, although it may not be 22. Check both UFW and any firewall or security group provided by your VPS company.<\/p>\n<\/details>\n<details class=\"aiw-faq-item\">\n<summary>Why does Nginx still show the default page after I configure my domain?<\/summary>\n<p>The domain may still point to another IP, the default site may still be enabled, or your server block may not match the Host header. Check dig +short A example.com, inspect sites-enabled, run nginx -T, and test with curl -I -H &#039;Host: example.com&#039; http:\/\/SERVER_IP.<\/p>\n<\/details>\n<details class=\"aiw-faq-item\">\n<summary>What does nginx -t check?<\/summary>\n<p>It checks Nginx configuration syntax and verifies that the configuration can be loaded. It catches issues such as missing semicolons, invalid directives, and missing referenced files. A successful test does not prove that DNS, firewall access, or your upstream application is working.<\/p>\n<\/details>\n<details class=\"aiw-faq-item\">\n<summary>Should I use reload or restart after changing Nginx?<\/summary>\n<p>Use reload for normal configuration changes after a successful nginx -t. Nginx can start workers with the new configuration while existing workers finish current requests. A restart stops and starts the service and may create an avoidable interruption, so reserve it for cases where a reload is insufficient.<\/p>\n<\/details>\n<details class=\"aiw-faq-item\">\n<summary>How do I troubleshoot a 502 Bad Gateway response?<\/summary>\n<p>First check the Nginx error log and the upstream service. Confirm that the application is listening on the expected TCP port or Unix socket, then verify socket ownership and permissions. A 502 often means Nginx can run but cannot connect to its backend. journalctl, ss -ltnp, and the application service status usually narrow the problem quickly.<\/p>\n<\/details>\n<\/div>\n<h2 id=\"sources\">Sources<\/h2>\n<ul class=\"aiw-sources\">\n<li><a href=\"https:\/\/nginx.org\/en\/docs\/\" target=\"_blank\" rel=\"noopener\">Nginx Official Documentation<\/a> \u2014 nginx.org<\/li>\n<li><a href=\"https:\/\/documentation.ubuntu.com\/server\/how-to\/web-services\/install-nginx\/\" target=\"_blank\" rel=\"noopener\">Ubuntu Server Documentation &#8211; Install Nginx<\/a> \u2014 documentation.ubuntu.com<\/li>\n<li><a href=\"https:\/\/ubuntu.com\/\" target=\"_blank\" rel=\"noopener\">Ubuntu Server Documentation &#8211; Firewalls<\/a> \u2014 ubuntu.com<\/li>\n<li><a href=\"https:\/\/letsencrypt.org\/docs\/challenge-types\/\" target=\"_blank\" rel=\"noopener\">Let&#039;s Encrypt &#8211; Challenge Types<\/a> \u2014 letsencrypt.org<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Install Nginx on Ubuntu, configure UFW, create a domain server block, verify DNS, troubleshoot logs, and prepare the server for HTTPS.<\/p>\n","protected":false},"author":2,"featured_media":885,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-887","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux"],"lang":"en","translations":{"en":887,"tr":886},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts\/887","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/comments?post=887"}],"version-history":[{"count":1,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts\/887\/revisions"}],"predecessor-version":[{"id":889,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts\/887\/revisions\/889"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/media\/885"}],"wp:attachment":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/media?parent=887"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/categories?post=887"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/tags?post=887"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}