Reference Guide Detailed deployment notes with production context and concrete examples.

Flask Nginx Config Test Failed (Fix Guide)

If you're seeing an Nginx config test failure while deploying or updating a Flask app, this guide shows you how to identify the invalid directive, fix the configuration, and validate the reload safely. The goal is to get nginx -t passing and restore a working reverse proxy setup for Flask.

Quick Fix / Quick Setup

Run the validation commands first and use the exact file and line number from the error output:

bash
sudo nginx -t
sudo systemctl status nginx --no-pager -l
sudo journalctl -u nginx -n 50 --no-pager
sudo nginx -T | sed -n '1,220p'

# Common fast checks
sudo ls -l /etc/nginx/sites-enabled/
sudo grep -R "server_name\|listen\|proxy_pass\|include\|ssl_certificate" /etc/nginx/sites-enabled /etc/nginx/nginx.conf

# After fixing config
sudo nginx -t && sudo systemctl reload nginx

Start with nginx -t and journalctl to get the exact file and line number. Most failures are caused by syntax errors, missing included files, bad upstream/socket paths, duplicate directives, or SSL file path mistakes.

What’s Happening

Nginx validates its full configuration tree before reload or restart. A failure means at least one file contains invalid syntax, an unsupported directive context, a missing file, or a conflicting server definition. Flask deployments commonly fail config tests when proxy_pass, include paths, Unix socket paths, static/media aliases, or Certbot-generated SSL directives are incorrect.

Step-by-Step Guide

  1. Run the config test and capture the exact error
    bash
    sudo nginx -t
    

    Example errors:
    text
    nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/flask-app:29
    nginx: [emerg] open() "/etc/nginx/snippets/ssl-common.conf" failed (2: No such file or directory)
    nginx: [emerg] unknown directive "prox_pass" in /etc/nginx/sites-enabled/flask-app:18
    
  2. Print the active merged configuration
    This helps when the error comes from an included file or symlinked site.
    bash
    sudo nginx -T
    

    To inspect only the first section quickly:
    bash
    sudo nginx -T | sed -n '1,220p'
    
  3. Open the failing file
    Use the exact path reported by nginx -t.
    bash
    sudo editor /etc/nginx/sites-available/your-site
    

    Or open the specific file from the error output.
  4. Fix basic syntax problems first
    Look for:
    • missing ;
    • extra or missing { / }
    • malformed quotes
    • directives placed outside valid blocks

    Example of a broken config:
    nginx
    server {
        listen 80
        server_name example.com
    
        location / {
            proxy_pass http://127.0.0.1:8000
        }
    }
    

    Correct version:
    nginx
    server {
        listen 80;
        server_name example.com;
    
        location / {
            proxy_pass http://127.0.0.1:8000;
        }
    }
    
  5. Verify directive context
    Some directives must appear only inside specific blocks.
    Invalid:
    nginx
    proxy_pass http://127.0.0.1:8000;
    

    Valid:
    nginx
    server {
        listen 80;
        server_name example.com;
    
        location / {
            proxy_pass http://127.0.0.1:8000;
        }
    }
    

    location must be inside server. proxy_pass must be inside location, if in some contexts, or specific upstream-related contexts.
  6. Check included files
    If you use include, confirm the target file exists.
    bash
    sudo find /etc/nginx -maxdepth 3 -type f | sort
    sudo ls -l /etc/nginx/snippets/
    sudo ls -l /etc/nginx/sites-enabled/
    

    Example:
    nginx
    include /etc/nginx/snippets/flask-proxy.conf;
    

    If that file is missing, either restore it or remove the include.
  7. Validate Flask reverse proxy settings
    For a Gunicorn TCP port:
    nginx
    server {
        listen 80;
        server_name example.com;
    
        location / {
            proxy_pass http://127.0.0.1:8000;
            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;
        }
    }
    

    For a Gunicorn Unix socket:
    nginx
    server {
        listen 80;
        server_name example.com;
    
        location / {
            proxy_pass http://unix:/run/gunicorn.sock;
            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;
        }
    }
    

    If you need the full deployment baseline, see Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide).
  8. Check Gunicorn socket or port references
    Confirm the Nginx target matches the actual Gunicorn service.
    bash
    sudo ls -l /run/gunicorn.sock
    curl -I http://127.0.0.1:8000
    curl --unix-socket /run/gunicorn.sock http://localhost/
    

    A bad socket path usually causes runtime upstream errors, but malformed syntax in proxy_pass can fail validation.
  9. Validate static and media configuration
    Incorrect alias usage is common in Flask deployments.
    Correct alias example:
    nginx
    location /static/ {
        alias /srv/flask-app/static/;
    }
    
    location /media/ {
        alias /srv/flask-app/media/;
    }
    

    Common mistakes:
    • using a relative path
    • missing trailing slash with alias
    • mixing root and alias incorrectly for the same location

    If static assets are the main issue, use Flask Static Files Not Loading in Production.
  10. Check SSL certificate directives
    If the config includes HTTPS, verify certificate paths.
    nginx
    server {
        listen 443 ssl;
        server_name example.com;
    
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    }
    

    Validate file paths:
    bash
    sudo ls -l /etc/letsencrypt/live/example.com/
    

    Missing or invalid certificate files will fail nginx -t.
  11. Check for duplicate or conflicting server blocks
    Search across all Nginx config files:
    bash
    sudo grep -R "server_name\|listen\|default_server" /etc/nginx
    

    Look for:
    • duplicate server_name entries
    • multiple listen 443 ssl default_server
    • duplicate enabled site symlinks
    • conflicting test/staging configs left in sites-enabled
  12. Check for unknown or unsupported directives
    If the error says unknown directive, verify spelling and support in your installed Nginx version.
    Example typo:
    nginx
    prox_pass http://127.0.0.1:8000;
    

    Correct:
    nginx
    proxy_pass http://127.0.0.1:8000;
    
  13. Inspect enabled symlinks
    A broken or duplicate symlink in sites-enabled can cause Nginx to read the wrong file.
    bash
    sudo ls -l /etc/nginx/sites-enabled/
    

    If needed, recreate the symlink:
    bash
    sudo ln -s /etc/nginx/sites-available/your-site /etc/nginx/sites-enabled/your-site
    
  14. Re-test and reload
    After each fix:
    bash
    sudo nginx -t
    

    If validation passes:
    bash
    sudo systemctl reload nginx
    
  15. Verify the site
    Test both HTTP and HTTPS if enabled:
    bash
    curl -I http://your-domain
    curl -Ik https://your-domain
    

    If config validates but requests still fail, continue with Fix: Nginx Not Connecting to Gunicorn (Connection Refused).

Common Causes

  • Missing semicolon or unmatched brace → Nginx stops parsing the file → fix the exact line reported by nginx -t.
  • Directive in the wrong context → Example: location or proxy_pass placed outside server or invalid nesting → move it to a valid block.
  • Broken include pathinclude references a file that does not exist → correct the path or remove the include.
  • Invalid SSL certificate pathssl_certificate or key file missing after Certbot/manual changes → update paths and verify files exist.
  • Duplicate server block settings → conflicting server_name, listen, or default_server across enabled sites → remove duplicates or consolidate definitions.
  • Bad proxy_pass syntax → malformed upstream URL or Unix socket syntax → use a valid http://127.0.0.1:8000; target or correct socket format.
  • Incorrect static/media alias → wrong alias syntax or missing trailing slash causes parse/runtime issues → use absolute paths and consistent location blocks.
  • Unsupported or misspelled directive → directive not available in your installed Nginx version/module → replace or remove it.
  • Broken symlink in sites-enabled → enabled config points to a missing file → recreate the symlink or disable the site.
  • Edited the wrong file → config test reads a different enabled file than expected → inspect nginx -T and sites-enabled to find the active source.

Debugging Section

Use these commands to isolate the failure:

bash
sudo nginx -t
sudo nginx -T
sudo systemctl status nginx --no-pager -l
sudo journalctl -u nginx -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/error.log
sudo ls -l /etc/nginx/sites-enabled/
sudo find /etc/nginx -maxdepth 3 -type f | sort
sudo grep -R "server_name\|listen\|proxy_pass\|include\|ssl_certificate\|ssl_certificate_key" /etc/nginx
sudo ls -l /etc/letsencrypt/live/your-domain/
sudo ls -l /run/gunicorn.sock
curl -I http://127.0.0.1:8000
curl --unix-socket /run/gunicorn.sock http://localhost/

What to look for:

  • nginx: [emerg] lines with exact file and line number
  • missing include targets
  • wrong SSL file paths
  • unexpected active site configs in sites-enabled
  • malformed proxy_pass syntax
  • direct Gunicorn access working while Nginx still fails, which indicates an Nginx-only issue

If Nginx passes validation but upstream requests fail, check Fix: Nginx Not Connecting to Gunicorn (Connection Refused).

Checklist

  • sudo nginx -t returns syntax is ok and test is successful
  • The failing file and line were reviewed and corrected
  • All include paths reference existing files
  • proxy_pass target matches the running Gunicorn port or socket
  • SSL certificate and key paths exist if HTTPS is enabled
  • Static and media root or alias paths are valid absolute paths
  • Nginx reload succeeds with sudo systemctl reload nginx
  • The Flask app responds through Nginx over HTTP or HTTPS as expected
  • Final production checks are complete using Flask Production Checklist (Everything You Must Do)

FAQ

Q: What is the fastest way to find the broken Nginx config?
A: Run sudo nginx -t first. It usually prints the exact file and line number causing the failure.

Q: Does a failed nginx -t mean my Flask app is broken?
A: Not necessarily. It means the new Nginx config cannot be validated. Gunicorn or Flask may still be running normally behind it.

Q: Why does Nginx complain about a file I did not edit?
A: Nginx loads included files and enabled site symlinks. The actual failing directive may be in an included snippet or another enabled server block.

Q: Can I reload Nginx if nginx -t fails?
A: No. Fix the validation error first. Reload only after the config test succeeds.

Q: How do I check whether the issue is Nginx or Gunicorn?
A: Validate Nginx syntax with nginx -t, then test the Gunicorn port or socket directly with curl. If direct Gunicorn access works, focus on Nginx config.

Q: Why does nginx -t fail but Nginx is still serving traffic?
A: The current running config remains active until a reload or restart applies the new broken config.

Q: What does unknown directive mean?
A: The directive is misspelled, placed in the wrong context, or unsupported by your installed Nginx build or version.

Q: Can a missing SSL file break config validation?
A: Yes. Invalid ssl_certificate or ssl_certificate_key paths will fail the config test.

Q: Can a bad Gunicorn socket path fail nginx -t?
A: Usually not unless the syntax is malformed; it more commonly causes runtime upstream errors after Nginx starts.

Q: Should I use reload or restart after fixing config?
A: Use reload after nginx -t passes so the active process updates without a full stop.

Final Takeaway

An Nginx config test failure is usually resolved by reading the exact file and line from nginx -t, correcting syntax or file path issues, validating the merged config with nginx -T, and only then reloading Nginx. For Flask deployments, the most common breakpoints are proxy targets, include files, static aliases, SSL paths, and duplicate server definitions.