After spending hours configuring a Windows 2008 EC2 instance with Tomcat 7 and deploying a Java web application, I hit a frustrating roadblock. While local access worked perfectly through localhost:8080
, all attempts to reach the application via public IP resulted in "Web page not available" errors.
Like most developers, I started with the obvious troubleshooting steps:
1. Confirmed localhost access (Tomcat running)
2. Configured Security Group inbound rules:
- HTTP (port 80) 0.0.0.0/0
- Custom TCP (port 8080) 0.0.0.0/0
3. Disabled Windows Firewall completely
4. Verified Elastic IP association
The solution emerged when I realized Windows 2008 Server binds Tomcat to 127.0.0.1 by default. Here's how to fix it:
1. Open server.xml in Tomcat's conf directory
2. Locate the Connector configuration:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
3. Add address="0.0.0.0" attribute:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
address="0.0.0.0" />
For production environments, consider these enhancements:
# Configure Tomcat to run on port 80 (requires admin privileges)
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
address="0.0.0.0" />
# Or set up URL rewriting in Apache (if using httpd)
RewriteEngine On
RewriteRule ^/(.*) http://localhost:8080/$1 [P]
After making changes:
1. netstat -ano | findstr :8080 # Verify listening on 0.0.0.0
2. telnet your-public-ip 8080 # Test connectivity
3. Restart Tomcat service completely
4. Check CloudWatch logs for any blocked requests
When your Tomcat web application runs locally but fails via public IP, start with these diagnostic commands:
# Check local Tomcat binding (run on EC2 instance)
netstat -ano | findstr :80
# Typical correct output showing LISTENING state
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 1234
The AWS security group requires explicit inbound rules. Here's how to verify them programmatically using AWS CLI:
aws ec2 describe-security-groups \
--group-ids sg-xxxxxxxx \
--query 'SecurityGroups[0].IpPermissions' \
--output table
For manual verification, ensure your inbound rule matches this pattern:
- Type: HTTP (port 80)
- Source: 0.0.0.0/0 (for testing) or your specific IP range
Create a permanent firewall rule via PowerShell:
New-NetFirewallRule -DisplayName "Allow HTTP 80" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
Verify your connector configuration in conf/server.xml
:
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
address="0.0.0.0" />
The address="0.0.0.0"
parameter is crucial for external access.
Don't overlook VPC-level network ACLs. They can override security group rules. Check with:
aws ec2 describe-network-acls \
--filters Name=association.subnet-id,Values=subnet-xxxxxx \
--query 'NetworkAcls[0].Entries'
- Test localhost access on EC2:
curl http://localhost
- Test via private IP from another EC2 instance
- Test via public IP from external network
If using DNS, verify resolution with:
nslookup yourdomain.com
ping yourdomain.com
For Elastic IPs, confirm association status:
aws ec2 describe-addresses --public-ips x.x.x.x