Introduction

After tightening security by reducing the allowed request body size in nginx, load balancer, or Tower's internal API configuration, Ansible Tower or AWX starts rejecting valid job launches, inventory imports, and API calls. The 413 "Request Entity Too Large" error appears when users try to launch jobs with large extra_vars, upload sizable inventory files, or make API calls with extensive payload data.

This commonly occurs after: - Security hardening that reduces client_max_body_size in nginx - Setting strict limits in a corporate load balancer (F5, HAProxy, AWS ALB) - Modifying Tower's REST API framework limits - Deploying Tower behind a new reverse proxy

Symptoms

In browser and API responses:

json
{
  "error": "413 Request Entity Too Large",
  "detail": "The request body exceeded the maximum allowed size"
}

In Tower UI:

``` Error launching job

Request failed with status 413 The request entity is too large. Please reduce the size of your request. ```

In nginx error logs:

``` # /var/log/nginx/error.log 2024-03-15 14:23:45 [error] 12345#0: *67890 client intended to send too large body: 1048577 bytes, client: 10.0.1.100, server: tower.example.com, request: "POST /api/v2/job_templates/42/launch/ HTTP/1.1", host: "tower.example.com", referrer: "https://tower.example.com/"

2024-03-15 15:12:34 [error] 12345#0: *67891 client intended to send too large body: 5242881 bytes, client: 10.0.1.101, server: tower.example.com, request: "POST /api/v2/inventories/15/update/ HTTP/1.1" ```

In Tower task logs:

bash
2024-03-15 14:24:12,456 ERROR awx.api.views Job launch failed: Request body too large
2024-03-15 14:24:12,789 WARNING awx.main.tasks Job template 42 launch rejected: extra_vars size 1.5MB exceeds limit

In HAProxy logs:

bash
Mar 15 14:23:45 haproxy[12345]: 10.0.1.100:54321 [15/Mar/2024:14:23:45.123] tower_front tower_back/tower-primary 0/0/0/1/1 413 212 - - ---- 1/1/0/0/0 0/0 "POST /api/v2/job_templates/42/launch/ HTTP/1.1"

In AWS ALB access logs:

json
{
  "type": "request",
  "elb": "tower-alb",
  "listenerPort": 443,
  "request": {
    "method": "POST",
    "path": "/api/v2/job_templates/42/launch/",
    "size": 2097153
  },
  "response": {
    "statusCode": 413,
    "statusDescription": "HTTP 413 Payload Too Large"
  }
}

Common Causes

The 413 error occurs when the request body size exceeds limits at any layer in the request path:

  1. 1.**nginx client_max_body_size**: The default is 1MB, but Tower installations often need 10-50MB for large inventory files and job template extra_vars. Tightening this to 1MB or less blocks legitimate Tower operations.
  2. 2.Load balancer limits: Corporate load balancers (F5, HAProxy) often have default body size limits. AWS ALB has a 1MB default, and Google Cloud Load Balancer has a 1MB limit that cannot be increased.
  3. 3.Django REST Framework limits: Tower's API framework (rest_framework) can have DATA_UPLOAD_MAX_MEMORY_SIZE set to a restrictive value.
  4. 4.gunicorn/uvicorn limits: Application servers may have request body limits configured.
  5. 5.Proxy chain multiplication: Requests pass through multiple proxies (ALB -> nginx -> Tower), and each can enforce its own limit.
  6. 6.Large extra_vars in job templates: Complex automation workflows often require passing substantial JSON/YAML data structures through extra_vars.

Step-by-Step Fix

Step 1: Identify Which Layer is Rejecting

Check each layer in the request path:

```bash # Check nginx configuration sudo grep -r "client_max_body_size" /etc/nginx/

# Default nginx config for Tower cat /etc/nginx/nginx.conf | grep -A5 -B5 "client_max_body_size"

# Check current effective limit curl -X POST -k -u admin:password \ -H "Content-Type: application/json" \ -d '{"extra_vars": "'$(python3 -c "print('{\"test\": \"' + 'x'*2000000 + '\"}')")'"}' \ https://tower.example.com/api/v2/job_templates/1/launch/

# Check Tower's Django settings grep -r "DATA_UPLOAD_MAX_MEMORY_SIZE" /etc/tower/ grep -r "DATA_UPLOAD_MAX_MEMORY_SIZE" /var/lib/awx/

# Check HAProxy configuration (if applicable) sudo grep -r "max.*body|req.*len" /etc/haproxy/

# Check F5 configuration (if applicable) # Via F5 web UI: Local Traffic > Profiles > Services > HTTP # Look for "Maximum Header Size" and related settings ```

Step 2: Fix nginx Configuration

Update nginx to allow larger requests:

```bash # Edit nginx configuration sudo vim /etc/nginx/nginx.conf

# In the http block, increase the limit http { # Allow up to 100MB for Tower operations client_max_body_size 100M;

# Also set larger buffers for large headers client_body_buffer_size 1M; large_client_header_buffers 4 16k;

# ... rest of configuration }

# Or set per-location limits sudo vim /etc/nginx/conf.d/tower.conf

server { listen 443 ssl; server_name tower.example.com;

# General API limit location /api/ { client_max_body_size 50M; proxy_pass http://tower_api; }

# Higher limit for inventory imports location /api/v2/inventories/ { client_max_body_size 200M; proxy_pass http://tower_api; }

# Higher limit for project updates location /api/v2/projects/ { client_max_body_size 100M; proxy_pass http://tower_api; } }

# Test configuration sudo nginx -t

# Reload nginx sudo systemctl reload nginx ```

Step 3: Fix Tower Django Settings

Update Tower's internal API limits:

```bash # Edit Tower settings sudo vim /etc/tower/settings.py

# Add or modify these settings # Maximum memory size for request body (in bytes) DATA_UPLOAD_MAX_MEMORY_SIZE = 104857600 # 100MB

# Maximum number of form fields DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000

# For Tower 3.8+ / AWX, also check FILE_UPLOAD_MAX_MEMORY_SIZE = 104857600 # 100MB

# Restart Tower services sudo ansible-tower-service restart ```

Step 4: Fix HAProxy Configuration

If using HAProxy as a load balancer:

```bash # Edit HAProxy configuration sudo vim /etc/haproxy/haproxy.cfg

frontend tower_front bind *:443 ssl crt /etc/ssl/tower.pem # Increase request body limit to 100MB http-request set-var(req.body_len) req.body_len http-request deny if { req.body_len gt 104857600 }

# Or use option http-buffer-request with larger limits option http-buffer-request tune.http.maxhdr 32768

default_backend tower_back

backend tower_back balance roundrobin server tower1 10.0.1.10:8080 check server tower2 10.0.1.11:8080 check

# Restart HAProxy sudo systemctl restart haproxy ```

Step 5: Fix AWS ALB Configuration

If using AWS Application Load Balancer:

```bash # AWS ALB has a hard 1MB limit for request bodies # Options to work around:

# Option 1: Use Network Load Balancer instead (no body size limit) aws elbv2 create-load-balancer \ --name tower-nlb \ --type network \ --subnets subnet-12345 subnet-67890

# Option 2: Use CloudFront + ALB # Configure CloudFront to forward requests to ALB # CloudFront supports up to 10,240 bytes for query strings # and has different body size handling

# Option 3: Change API design to use chunked uploads or S3 # For large inventories, upload to S3 first, then reference aws s3 cp inventory.yaml s3://tower-inventory-bucket/ # Then POST with reference: curl -X POST -H "Content-Type: application/json" \ -d '{"inventory_source": "s3://tower-inventory-bucket/inventory.yaml"}' \ https://tower.example.com/api/v2/inventories/1/update/ ```

Step 6: Fix gunicorn Configuration

Update Tower's application server settings:

```bash # Find gunicorn configuration sudo find /etc -name "*gunicorn*" -o -name "*supervisor*"

# Edit supervisor configuration for Tower sudo vim /etc/supervisord.d/tower.conf

[program:tower-api] command=/var/lib/awx/venv/awx/bin/gunicorn --config /etc/tower/gunicorn_conf.py awx.wsgi:application # gunicorn config file sudo vim /etc/tower/gunicorn_conf.py

# Increase limits limit_request_line = 0 # Unlimited request line limit_request_fields = 200 limit_request_field_size = 0 # Unlimited field size

# Restart services sudo supervisorctl restart tower-api ```

Step 7: Create a Test Script

Verify the configuration works with your largest expected payloads:

```bash #!/bin/bash # test_request_size.sh

TOWER_URL="https://tower.example.com" ADMIN_USER="admin" ADMIN_PASS="password"

# Test different sizes for size_mb in 1 5 10 25 50 100; do size_bytes=$((size_mb * 1024 * 1024)) echo "Testing ${size_mb}MB request..."

# Generate test payload payload=$(python3 -c " import json import sys size = $size_bytes # Create JSON with repeated data data = {'test_data': 'x' * (size - 100)} print(json.dumps(data)) ")

# Test job launch response=$(curl -s -o /dev/null -w "%{http_code}" \ -X POST -k -u "$ADMIN_USER:$ADMIN_PASS" \ -H "Content-Type: application/json" \ -d "$payload" \ "$TOWER_URL/api/v2/job_templates/1/launch/")

if [ "$response" -eq 413 ]; then echo "FAILED: ${size_mb}MB request rejected (413)" elif [ "$response" -eq 201 ] || [ "$response" -eq 200 ]; then echo "SUCCESS: ${size_mb}MB request accepted" else echo "UNEXPECTED: ${size_mb}MB request got HTTP $response" fi done ```

Verification

Test with actual Tower operations:

```bash # Test job launch with large extra_vars curl -X POST -k -u admin:password \ -H "Content-Type: application/json" \ -d '{"extra_vars": "@large_vars.json"}' \ https://tower.example.com/api/v2/job_templates/42/launch/

# Expected output: { "job": 1234, "ignored_fields": {}, "id": 1234, "type": "job", "url": "/api/v2/jobs/1234/", "status": "pending" }

# Test inventory import with large file curl -X POST -k -u admin:password \ -H "Content-Type: application/json" \ -d @large_inventory.json \ https://tower.example.com/api/v2/inventories/15/update/

# Check nginx access logs for successful requests sudo tail -f /var/log/nginx/access.log | grep -E "POST.*launch|POST.*update"

# Should see 201/200 status codes, not 413 # 10.0.1.100 - - [15/Mar/2024:14:30:45 +0000] "POST /api/v2/job_templates/42/launch/ HTTP/1.1" 201 512 ```

  • [ansible-tower-behind-reverse-proxy](/articles/ansible-tower-behind-reverse-proxy)
  • [ansible-job-template-extra-vars-too-large](/articles/ansible-job-template-extra-vars-too-large)
  • [ansible-inventory-import-timeout](/articles/ansible-inventory-import-timeout)
  • [WordPress troubleshooting: Ansible Artifact Download Uses an Old Mi](ansible-artifact-download-uses-an-old-mirror-after-proxy-change)
  • [WordPress troubleshooting: Ansible Audit Trail Misses Events Under ](ansible-audit-trail-misses-events-under-burst-load)
  • [WordPress troubleshooting: Ansible Background Worker Gets Stuck in ](ansible-background-worker-stuck-in-a-retry-loop)
  • [WordPress troubleshooting: Ansible Backup Completes but Restore Fai](ansible-backup-completes-but-restore-fails-checksum-validation)
  • [WordPress troubleshooting: Ansible Batch Importer Duplicates Rows A](ansible-batch-importer-duplicates-rows-after-a-retry)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "WordPress troubleshooting: Ansible Request Body Is Rejected After a", "description": "Learn how to fix Ansible Request Body Is Rejected After a Size Limit Tightening. Professional WordPress troubleshooting solutions with step-by-step guidance. WP error fix, WordPress optimization, WP security, WordPress performance.", "url": "https://www.fixwikihub.com/ansible-request-body-rejected-after-size-limit-tightening", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-02-12T10:57:32.518Z", "dateModified": "2026-02-12T10:57:32.518Z" } </script>