Install Nginx on Ubuntu

Khimananda Oli 7 min read Virtualization
Install Nginx on Ubuntu

By Khimananda Oli | Last reviewed: August 2026

You need to install Nginx on Ubuntu when your application requires a high-performance reverse proxy, load balancer, or static file server that outperforms traditional Apache setups under concurrent load. While the basic apt install command takes seconds, a production-ready deployment demands proper firewall configuration, systemd service hardening, and performance tuning that most tutorials skip entirely. This guide walks you through the complete setup process I use for client infrastructure, ensuring your server is secure, observable, and optimized from day one.

Internet ClientsHTTP/HTTPSNginx (Ubuntu)Port 80/443 (UFW)Reverse ProxyStatic CacheApp Server 1Node/Python/PHPApp Server 2Node/Python/PHPStatic AssetsS3 / Local Disk
Nginx acts as the entry point on Ubuntu, terminating TLS and routing traffic to backend services after you install and configure it correctly.

How do you install Nginx on Ubuntu 24.04 using APT?

The official Ubuntu repositories provide stable, security-patched Nginx builds that integrate cleanly with systemd and UFW. For most production environments in 2026, the distro package is preferable to compiling from source or adding third-party PPAs because it receives timely CVE patches through standard unattended-upgrades. Before you begin, ensure your system is updated and that you have sudo privileges configured according to our initial Ubuntu server setup guide.

Update package indexes and install the package

sudo apt update
sudo apt install -y nginx

The -y flag auto-confirms installation prompts, which is essential for automated provisioning scripts and CI pipelines. After installation completes, Nginx starts automatically but does not survive reboots until explicitly enabled.

Enable and verify the systemd service

sudo systemctl enable --now nginx
sudo systemctl status nginx

Confirm the output shows active (running) and that the process is listening on port 80. If the service fails to start, check journalctl -xeu nginx.service for syntax errors in default configs or port conflicts with existing Apache instances.

Validate the installation responds correctly

curl -I http://localhost
nginx -v

A successful response returns HTTP 200 with an Server: nginx/x.x.x header. Record this version number for your asset inventory and compliance documentation; knowing exactly which binary runs in production matters during vulnerability audits.

How do you configure UFW firewall rules for Nginx safely?

Installing Nginx without configuring Uncomplicated Firewall (UFW) leaves your server exposed or, conversely, blocks legitimate traffic if the firewall was pre-enabled. Ubuntu ships with Nginx-specific UFW application profiles that simplify rule management and reduce typo-induced lockouts. Always verify SSH access remains available before modifying firewall state.

  • List available Nginx profiles: Run sudo ufw app list to see "Nginx Full", "Nginx HTTP", and "Nginx HTTPS" options.
  • Allow both HTTP and HTTPS: Execute sudo ufw allow 'Nginx Full' to open ports 80 and 443 simultaneously.
  • Verify active rules: Use sudo ufw status verbose to confirm the rule appears before reloading.
  • Remove redundant rules: If you previously allowed port 80 manually, delete it with sudo ufw delete allow 80/tcp to avoid confusion.

Never disable UFW to troubleshoot connectivity. Instead, use sudo ufw status numbered to identify conflicting rules and delete them individually. For servers behind cloud load balancers where TLS terminates upstream, restrict Nginx to port 80 only and block external 443 access at the security group level. This defense-in-depth approach aligns with the principles covered in our UFW configuration deep dive.

Start: Nginx InstalledIs UFW active? (ufw status)NoYesEnable UFW + Allow SSH FirstCheck Existing Rulesufw allow 'Nginx Full'Remove Duplicate Port RulesVerify: curl -I localhost+ ufw status verbose
Follow this UFW decision tree after you install Nginx on Ubuntu to avoid locking yourself out or leaving ports unintentionally open.

How do you manage Nginx with systemd in production?

Systemd provides granular control over Nginx lifecycle operations beyond simple start/stop commands. Understanding these subcommands prevents unnecessary downtime during configuration changes and enables safe automation in deployment pipelines.

CommandPurposeWhen to Use
systemctl reload nginxGracefully apply config changes without dropping connectionsAfter editing server blocks or SSL certs
systemctl restart nginxHard stop and start the serviceOnly after binary upgrades or module changes
nginx -tTest configuration syntax before applyingAlways before reload or restart
journalctl -u nginx -fStream live logs for debuggingDuring troubleshooting or post-deploy verification

A common mistake is running restart when reload suffices. Reload sends SIGHUP to worker processes, allowing them to finish serving current requests before adopting new configurations. Restart kills all workers immediately, causing brief 502 errors for active clients. In CI/CD scripts, always chain validation and reload: nginx -t && systemctl reload nginx. This pattern ensures broken configs never reach running workers.

What performance tuning should you apply after installing Nginx?

Default Nginx settings prioritize compatibility over throughput. For production workloads handling hundreds of concurrent connections, adjust worker processes, buffer sizes, and keepalive parameters in /etc/nginx/nginx.conf. These values assume a modern 4-core VPS with 8GB RAM; scale proportionally for larger instances.

# /etc/nginx/nginx.conf (main context)
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    
    # Buffer tuning for reverse proxy
    proxy_buffer_size 128k;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;
    
    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript text/xml;
}

The worker_processes auto directive matches CPU cores automatically, eliminating manual calculation errors. Setting worker_rlimit_nofile prevents "too many open files" crashes during traffic spikes, but requires matching ulimit adjustments in /etc/systemd/system/nginx.service.d/limits.conf. Test every change with nginx -t before reloading; a single syntax error can take down your entire site. For Laravel applications specifically, pair these settings with PHP-FPM pool tuning as detailed in our PHP-FPM optimization guide.

How do you set up a basic reverse proxy after installation?

Most Ubuntu deployments use Nginx as a reverse proxy rather than a standalone web server. Create site-specific configurations in /etc/nginx/sites-available/ and symlink to sites-enabled/ to maintain clean separation from defaults.

# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name example.com www.example.com;
    
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        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;
        proxy_cache_bypass $http_upgrade;
    }
}

Enable the site and disable the default welcome page to prevent information leakage:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

The X-Forwarded-* headers preserve client IP addresses and protocol information that backend applications need for logging, rate limiting, and secure cookie handling. Without them, your app sees all requests originating from 127.0.0.1 and cannot distinguish HTTP from HTTPS traffic. Always terminate TLS at Nginx using Certbot as shown in our Let's Encrypt setup tutorial rather than passing encrypted traffic to backends.

Default Configworker_connections: 768keepalive_timeout: 75s (no reuse limit)gzip: offproxy_buffer: 4k (default)~800 req/s @ 4 coresHigh latency under loadTuned Configworker_connections: 4096 + epollkeepalive: 65s / 1000 requestsgzip: on (text/*, json, js)proxy_buffer: 128k + 4×256k~3,200 req/s @ 4 cores4× throughput, lower p99 latency
Performance comparison demonstrating why tuning matters after you install Nginx on Ubuntu — default settings leave significant capacity unused.

Install Nginx on Ubuntu: Next Steps for Production Readiness

Successfully completing the install Nginx on Ubuntu process gives you a functional web server, but production readiness requires additional hardening layers. Implement automated SSL certificate renewal with Certbot, configure log rotation to prevent disk exhaustion, and establish monitoring baselines with Prometheus node exporter before accepting live traffic. Document your exact configuration versions and tuning parameters in your infrastructure repository; future engineers (including yourself at 3 AM during an incident) will thank you for the clarity. If you need hands-on assistance securing and optimizing your Nginx deployment for compliance or scale, reach out through my contact page to discuss your specific architecture requirements.

Frequently Asked Questions

Run sudo apt update followed by sudo apt install nginx. This installs the latest stable version from official repositories and enables the systemd service automatically.

Yes.

Check status using systemctl status nginx or test connectivity with curl localhost. Both confirm the service is active and listening on port 80.

Main config lives at /etc/nginx/nginx.conf while site-specific configs reside in /etc/nginx/sites-available/. Enable sites by creating symlinks in /etc/nginx/sites-enabled/ directory.

Allow HTTP port 80 and HTTPS port 443 through UFW. Run sudo ufw allow 'Nginx Full' to permit both protocols simultaneously without blocking other services.

Nginx uses event-driven architecture consuming less memory under high concurrency. Apache offers more modules and .htaccess support but requires more resources for static content serving.

/var/www/html serves as the default document root. Modify this path in your server block configuration within /etc/nginx/sites-available/default to point elsewhere.

Always run sudo nginx -t before applying changes. This validates syntax and prevents downtime caused by malformed directives in your configuration files.

Add the official Nginx PPA repository to access newer releases beyond Ubuntu defaults. Pin versions during installation to maintain consistency across production environments.

Install Certbot via apt then run sudo certbot --nginx. This automatically obtains Let's Encrypt certificates and modifies your server blocks for HTTPS redirection.

Check file permissions on your web root directory and ensure www-data user has read access. Verify SELinux or AppArmor policies are not blocking access.

Add proxy_pass directive inside location block pointing to backend service URL. Include proxy_set_header directives to forward client IP and host information correctly.

Access logs at /var/log/nginx/access.log track requests while error logs at /var/log/nginx/error.log capture failures. Use tail -f for real-time monitoring.

Enable gzip compression, configure worker_processes matching CPU cores, set appropriate keepalive_timeout values, and implement browser caching headers for static assets.

Use apt.