UFW Firewall Rules for Web Servers

Khimananda Oli 9 min read CI/CD and Automation
UFW Firewall Rules for Web Servers

By Khimananda Oli | Last reviewed: August 2026

Securing a production web server starts with a strict network perimeter, and UFW firewall rules for web servers provide the most efficient way to enforce that boundary on Ubuntu systems. Without a properly configured host-based firewall, your Nginx or Apache instance is exposed to port scanning, brute-force attacks, and unauthorized service discovery. This guide walks you through configuring UFW specifically for web workloads, covering essential allow/deny policies, application profiles, and logging strategies that align with modern DevOps security practices.

Internet TrafficUntrusted ZoneUFW FirewallDefault: DENY INWeb ServerNginx / ApacheALLOW 22/tcp (SSH)From Trusted IP OnlyALLOW 80/tcp (HTTP)Public Web TrafficALLOW 443/tcp (HTTPS)Encrypted Web TrafficDENY 3306/tcpMySQL (Blocked)DENY 21/tcpFTP (Blocked)DENY ALL OTHERImplicit Default Policy
UFW firewall architecture for web servers: default deny inbound with explicit allow rules for SSH, HTTP, and HTTPS while blocking database and legacy protocols

How do you configure basic UFW firewall rules for web servers?

The foundation of any secure web server firewall is a default-deny policy combined with explicit allow rules for required services. Before enabling UFW, verify your current SSH connection method and ensure you have console access as a fallback — locking yourself out during initial configuration is a common mistake I see repeatedly in production environments.

Set default policies and enable UFW

Start by establishing the baseline security posture. UFW defaults to allowing all traffic when inactive, so you must set restrictive defaults before enabling the firewall:

# Set default incoming policy to deny
sudo ufw default deny incoming

# Allow outbound connections (required for updates, DNS, etc.)
sudo ufw default allow outgoing

# Verify SSH access rule exists BEFORE enabling
sudo ufw allow from YOUR_TRUSTED_IP proto tcp to any port 22

# Enable UFW with confirmation prompt
sudo ufw enable

Never enable UFW without first adding your SSH allow rule. If you are managing remote infrastructure in Nepal or globally where console access may be delayed, this step prevents costly recovery operations. For teams following our initial Ubuntu server setup guide, integrate these UFW commands into your provisioning scripts to ensure every new server starts with a hardened network perimeter.

Allow HTTP and HTTPS traffic

Web servers require ports 80 and 443 open for standard HTTP and HTTPS traffic. UFW provides application profiles that bundle related ports, reducing configuration errors:

# Option A: Use built-in Nginx profile (recommended)
sudo ufw allow 'Nginx Full'

# Option B: Explicit port rules (if no profile exists)
sudo ufw allow 80/tcp comment 'HTTP web traffic'
sudo ufw allow 443/tcp comment 'HTTPS encrypted traffic'

# Verify active rules
sudo ufw status verbose

The 'Nginx Full' profile opens both 80 and 443 in a single rule. If you are running Apache, use 'Apache Full' instead. Always add comments to custom rules — six months from now, you or another engineer will need to understand why a rule exists during an incident or audit.

What are the best practices for restricting SSH access with UFW?

Leaving SSH open to the entire internet is one of the most frequent security gaps I encounter during compliance audits. Brute-force attacks against port 22 are constant and automated; your firewall should reflect zero-trust principles even at the host level.

Restrict SSH to specific IP addresses or ranges

Replace the generic SSH allow rule with source-restricted rules tied to your team's known egress IPs:

# Delete overly permissive SSH rule
sudo ufw delete allow 22/tcp

# Allow SSH only from office VPN gateway
sudo ufw allow from 203.0.113.50 proto tcp to any port 22 comment 'Office VPN'

# Allow SSH from CI/CD runner subnet
sudo ufw allow from 10.0.4.0/24 proto tcp to any port 22 comment 'GitLab Runners'

# Allow SSH from backup management host
sudo ufw allow from 198.51.100.25 proto tcp to any port 22 comment 'Backup Server'

If your team uses dynamic IPs or multiple remote locations, consider combining UFW restrictions with a WireGuard or Tailscale mesh VPN. This approach keeps UFW rules static while providing secure access regardless of physical location. For deeper SSH hardening beyond firewall rules, refer to our SSH hardening guide which covers key-only authentication, fail2ban integration, and non-standard port configurations.

Handle IPv6 considerations

UFW manages IPv4 and IPv6 rules separately. If IPv6 is enabled on your server (check with cat /proc/sys/net/ipv6/conf/all/disable_ipv6), ensure your SSH restriction applies to both protocol families:

# Check if IPv6 is active in UFW config
grep IPV6 /etc/default/ufw

# If IPV6=yes, add matching IPv6 rules
sudo ufw allow from 2001:db8::50 proto tcp to any port 22 comment 'Office VPN v6'

Disabling IPv6 entirely is acceptable for many web servers, but if your organization requires dual-stack networking, audit both rule sets. Missing IPv6 restrictions create a bypass path that negates your IPv4 hardening.

1. Verify ConsoleAccess Available2. Add SSH RuleFrom Trusted IP3. Set DefaultsDeny In / Allow Out4. Enable UFWConfirm & Test SSH5. Add Web Rules80/tcp & 443/tcp6. Test Websitecurl & Browser Check7. Enable Loggingufw logging low8. Document RulesExport & Version ControlROLLBACK: sudo ufw disable → restores full connectivity if locked outAlways test in staging first; keep console session open during initial enable
Safe UFW enablement workflow for live web servers: sequential steps with verification checkpoints and rollback procedure to prevent lockouts

How do you manage UFW application profiles for Nginx and Apache?

Application profiles abstract port numbers into semantic names, making rules readable and reducing misconfiguration risk. UFW ships with profiles for common web servers stored in /etc/ufw/applications.d/.

List and inspect available profiles

# List all registered application profiles
sudo ufw app list

# Inspect what ports a profile includes
sudo ufw app info 'Nginx Full'
# Output: Ports 80,443/tcp

# Check Apache variants
sudo ufw app info 'Apache Full'
# Output: Ports 80,443/tcp

Profiles like 'Nginx HTTP' (port 80 only) or 'Nginx HTTPS' (port 443 only) exist for transitional setups, but production web servers should almost always use the 'Full' variant. Splitting HTTP and HTTPS into separate rules adds complexity without security benefit since modern sites redirect HTTP to HTTPS anyway.

Create custom application profiles

If you run non-standard services or want to group ports logically, create custom profiles:

sudo nano /etc/ufw/applications.d/custom-webapp
[CustomWebApp]
title=Custom Web Application Stack
description=Node.js app with Redis cache and health endpoint
ports=3000/tcp;6379/tcp;8080/tcp
# Register and apply the new profile
sudo ufw app update CustomWebApp
sudo ufw allow 'CustomWebApp' comment 'Production Node.js stack'

Store these profile files in version control alongside your infrastructure code. When provisioning new servers via Ansible or cloud-init, deploy the profile file before running UFW commands. This practice ensures consistency across environments and makes firewall configuration auditable — a requirement for SOC 2 and ISO 27001 compliance frameworks.

When should you use UFW logging and how do you interpret blocked traffic?

Firewall logs transform UFW from a silent gatekeeper into an observable security control. Without logging, you cannot detect attack patterns, troubleshoot legitimate blocked traffic, or produce evidence for compliance audits.

Configure appropriate log levels

UFW offers four verbosity levels. Choose based on your operational needs:

Log LevelUse CaseVolumeAudit Suitability
offTroubleshooting disabled; never in productionNoneNon-compliant
lowStable production servers; blocks onlyLowMinimum viable
mediumActive investigation; new deploymentsModerateRecommended default
highIncident response; forensic analysisHighTemporary use
# Set logging level (persists across reboots)
sudo ufw logging medium

# View recent UFW log entries
sudo grep -i ufw /var/log/kern.log | tail -50

# Extract blocked source IPs for analysis
sudo grep "UFW BLOCK" /var/log/kern.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -20

In my experience supporting teams across Nepal and international clients, medium logging strikes the right balance for most web servers. It captures blocked connection attempts with source/destination details without generating excessive noise. Pair UFW logs with centralized log aggregation using tools covered in our structured logging guide to correlate firewall events with application-level incidents.

Distinguish between expected and suspicious blocks

Not every blocked packet is an attack. Common legitimate sources include monitoring probes from new regions, CDN health checks after DNS changes, or internal services added without updating firewall rules. Establish a baseline of normal block patterns during the first week after deployment, then investigate deviations. Persistent blocks from single IPs targeting sensitive ports warrant fail2ban rules or upstream WAF blocking.

INSECURE CONFIGURATIONDefault Policy: ALLOW INCOMINGSSH 22/tcp OPEN TO 0.0.0.0/0HTTP 80/tcp OPENHTTPS 443/tcp OPENMySQL 3306/tcp EXPOSEDRedis 6379/tcp EXPOSEDALL OTHER PORTS ACCESSIBLERisk: Full attack surface exposedHARDENED CONFIGURATIONDefault Policy: DENY INCOMINGSSH 22/tcp FROM 203.0.113.50 ONLYHTTP 80/tcp ALLOW (Nginx Profile)HTTPS 443/tcp ALLOW (Nginx Profile)MySQL 3306/tcp BLOCKED BY DEFAULTRedis 6379/tcp BLOCKED BY DEFAULTALL OTHER PORTS IMPLICITLY DENIEDResult: Minimal attack surface, audit-ready
Side-by-side comparison of insecure default-allow versus hardened default-deny UFW configurations showing exposed services versus minimal attack surface

Secure Your Web Server Perimeter Today

Properly configured UFW firewall rules for web servers form the first line of defense in any production environment. The combination of default-deny policies, source-restricted SSH access, application profiles for web traffic, and appropriate logging creates a defensible perimeter that satisfies both security requirements and compliance frameworks. Do not treat firewall configuration as a one-time setup task; review and update your UFW rules whenever your application architecture changes, new team members join, or after security incidents reveal gaps. If your team needs assistance hardening server infrastructure or preparing for compliance audits, reach out to discuss your specific requirements.

Frequently Asked Questions

Always allow SSH port 22 before enabling UFW. Run sudo ufw allow 22/tcp then sudo ufw enable. Verify connectivity in a separate terminal session before closing your current connection to prevent accidental lockouts during initial firewall configuration.

Allow ports 80 and 443 for HTTP and HTTPS traffic plus SSH on port 22. Block everything else by default using sudo ufw default deny incoming. This minimal ruleset covers standard Nginx or Apache deployments serving Laravel applications securely in production environments.

Yes, use sudo ufw limit 80/tcp to restrict connections exceeding six attempts per thirty seconds. This basic rate limiting helps mitigate simple brute force attacks and connection flooding but lacks the sophistication of dedicated tools like fail2ban or Cloudflare WAF.

Use sudo ufw allow from 192.168.1.100 to any port 22 proto tcp to whitelist single IPs. Replace the address with your office or VPN subnet for broader access. This restricts sensitive management ports to trusted networks only while keeping public web ports open.

Yes, ensure IPV6=yes exists in /etc/default/ufw then reload. UFW automatically creates matching IPv6 rules when you define IPv4 rules if this setting is enabled. Most 2026 cloud providers assign dual-stack addresses requiring explicit IPv6 firewall coverage.

Run sudo ufw status verbose to see numbered rules with protocols and directions. Use sudo ufw status numbered for easier deletion reference. Check this output after every rule change to confirm intended behavior before considering the configuration complete.

Yes, run sudo ufw app list to see available profiles like Nginx Full or Apache Secure. Then execute sudo ufw allow 'Nginx Full' to open both ports 80 and 443 simultaneously. These predefined profiles reduce syntax errors during common web server setups.

First run sudo ufw status numbered to identify the exact rule number. Then execute sudo ufw delete [number] to remove it precisely. Always verify the remaining ruleset afterward to ensure no unintended gaps or duplicates were created during deletion.

Use UFW for most web servers as it simplifies rule management and reduces configuration errors. Reserve raw iptables for complex NAT scenarios or packet-level inspection that UFW cannot express. UFW wraps iptables reliably for standard HTTP and HTTPS filtering needs.

Enable logging with sudo ufw logging on then check /var/log/ufw.log for denied connections. Set logging to low medium or high based on volume tolerance. Review these logs regularly to identify attack patterns and validate that your deny rules function correctly.

Yes, set sudo ufw default deny outgoing then explicitly allow required destinations like package repositories and external APIs. This prevents reverse shells and data exfiltration but requires careful planning to avoid breaking application functionality during deployment or runtime operations.

Run sudo ufw disable to stop all filtering immediately without deleting rules. Re-enable with sudo ufw enable once debugging completes. Your previous ruleset persists across disable cycles making this safe for quick diagnostics during network or application troubleshooting sessions.

Yes, UFW saves rules automatically to /etc/ufw/user.rules and loads them via systemd at boot. No manual save command is needed unlike iptables. Verify persistence by checking sudo ufw status after restart to confirm all web server rules survived the reboot cycle.

Avoid managing Docker ports via UFW as Docker manipulates iptables directly bypassing UFW entirely. Instead bind containers to localhost and reverse proxy through Nginx on UFW-managed ports. This maintains firewall integrity while allowing containerized web applications to serve traffic safely.

Access the server via cloud provider console or VNC to run sudo ufw disable or fix rules locally. Most providers offer out-of-band recovery tools specifically for firewall lockouts. Always test rules in staging first and maintain console access credentials for production emergencies.