[HN Gopher] Gixy: Nginx Configuration Static Analyzer
       ___________________________________________________________________
        
       Gixy: Nginx Configuration Static Analyzer
        
       Author : mmsc
       Score  : 147 points
       Date   : 2025-02-16 04:06 UTC (18 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | cadamsdotcom wrote:
       | Nice work, tons of extra stuff vs the original.
       | 
       | Had a thought: imagine if it were a subcommand of nginx
       | (whichever fork will accept it) - that'd give it a much wider
       | audience.
       | 
       | Even more impactful would be if analysis always ran at nginx
       | startup. Wouldn't have to be blocking but getting warned about
       | risks would help more folks configure things more correctly more
       | often.
       | 
       | Either way great to have tools to help with correctly configuring
       | the parts of your infra that are exposed to the wild internet.
        
         | k1kingy wrote:
         | 'nginx -t' exists as a general syntax checker, would be neat to
         | expand it further to include these in depth checks.
        
           | progbits wrote:
           | What's annoying about the built-in checker is that it
           | attempts to connect proxypass backends. So if you want to run
           | this in CI you will get connection refused errors.
        
             | zelphirkalt wrote:
             | On the other hand, if it never checked those, you would run
             | into problems, when you rely on those being available and
             | somehow they are not.
        
             | ndsipa_pomu wrote:
             | Put the proxy settings into variables and you can sidestep
             | that. It also allows NgINX to start up when the backends
             | may not be running.
             | 
             | e.g.                   set $upstream_app         backend;
             | set $upstream_port        8888;         set $upstream_proto
             | http;         proxy_pass
             | $upstream_proto://$upstream_app:$upstream_port;
        
         | tetha wrote:
         | On the other hand, I've grown to like these tools being
         | separate, since it allows the check-tool to move faster.
         | Updating the thing all of your production requests go through
         | always has a bit of aprehension. Updating a config linter with
         | no prod-impact? Meh, just do it.
         | 
         | However, this would be great if a distribution wanted to
         | integrate it into their default nginx package (and maybe have a
         | nginx-minimal package around to install nginx without it).
         | Though e.g. debian has gotten hilarious amounts of flak in the
         | past for attempting things like this.
        
       | huang_chung wrote:
       | The need for a configuration file analyzer is a good sign your
       | software is overly complex and poorly architected.
       | 
       | Configuration files should be self-documenting.
       | 
       | Instead nginx taught us that if != if.
        
         | citrin_ru wrote:
         | I'm using nginx for many years (used mostly apache before that)
         | and would say as web servers configurations go nginx is one of
         | the easiest to work with. I've seen complex and hard to
         | understand nginx configs but they abused rewrite and logic
         | which they implement was complex itself.
         | 
         | add_header inheritance is counterintuitive bot once you know
         | how it works it should not be a problem. Another problematic
         | directive is "if" - AFAIK Igor (nginx creator) designed config
         | to be declarative but had to add "if" (imperative directive)
         | after numerous feature requests and "if" didn't fit existing
         | architecture well.
        
           | 9dev wrote:
           | Try Caddy once; it's a revelation. I have committed fairly
           | atrocious crimes with nginx over the years, only to figure
           | out just how much better I could have had it.
        
             | imcritic wrote:
             | I tried. I failed to configure it to work as a proxy that
             | proxypasses to php-fpm.
             | 
             | I'd call it's configuration way less intuitive than the one
             | of ngnix (and I wouldn't call myself a great enjoyer of
             | ngnix configuration).
        
             | CoolCold wrote:
             | I've tried to try - yet still on Nginx as my primary web
             | server and Apache somewhat secondary (with may be 5% for
             | Apache and 95% for Nginx) web server of choice.
             | 
             | No doubts I'm not an expert in Caddy and there are some
             | chances it has unique selling proposition, but I'm yet to
             | find it.
             | 
             | My take on Caddy was - something to let your quickly-
             | crafted-something-newshiny-loneley-dev-docker-container-to-
             | be-available-to-the-world - sort of the same case if I do
             | some tests (we call it MVP here) on my great-idea Flask app
             | and I need plain reverse proxy in front of it with SSL
             | termination, as noone except me and may be couple of Shodan
             | bots won't see.
             | 
             | Yet not mentioned unclear stable releases policy for Caddy.
        
         | bakugo wrote:
         | It's absolutely true that the nginx config has some really
         | obtuse features, "if" probably being the best example. But just
         | because they're there doesn't mean you have to use them, and
         | the documentation for "if" includes ample warning about its
         | pitfalls and openly advises against using it.
         | 
         | In fact, I'd argue that learning not to use them unless they're
         | absolutely necessary is a good lesson on the importance of
         | keeping things simple. When I was a beginner to web servers, I
         | spent quite a few hours wrangling nginx configs trying to do
         | things like fancy conditional redirects, removing .php
         | extensions from pages, etc.. But over the years I've slowly
         | learned that most of this logic belongs in application code,
         | not in nginx, and nowadays I can set up a new nginx server in
         | minutes because the configuration format is actually quite
         | simple and intuitive once you understand what you really need,
         | and what you should leave out or implement elsewhere.
        
       | mobilemidget wrote:
       | I already learned one thing regarding add_header
       | 
       | Worth the read already. Initially I even thought the analyzer was
       | 'wrong' but curl tests indeed shows that add_header replaces all,
       | surprisingly to me.
       | 
       | Thanks!
       | 
       | But I dont really like the installation of a pip/python ecosystem
       | but that is just my issue :) I now simply copy the configurations
       | from a python free servers and analyze them.
        
         | n3storm wrote:
         | Pipx or pyenv
        
         | eternal_braid wrote:
         | uv makes the experience of installing dependencies in Python
         | much better.
        
           | mobilemidget wrote:
           | actually I just dont want any python on my servers :)
        
       | ossusermivami wrote:
       | nice idea but i get that error when i try to use the docker image
       | (on a nixos env)
       | 
       | NameError: name 'SRE_FLAG_TEMPLATE' is not defined. Did you mean:
       | 'SRE_FLAG_VERBOSE'?
       | 
       | (using the mentioned docker command on README $ docker run --rm
       | -v `pwd`/nginx.conf:/etc/nginx/conf/nginx.conf getpagespeed/gixy
       | /etc/nginx/conf/nginx.conf)
        
       | zelphirkalt wrote:
       | NGINX config language grates on me. Whyyy did they have to come
       | up with their own config format? It is so much nicer to configure
       | Caddy with JSON file for example. Probably would also be much
       | easier to statically check things about the config, than having
       | to create a parser for NGINX config (or somehow integrate NGINX'
       | own parser maybe). Probably the best one can do is either have
       | NGINX at some point offer alternative config that uses JSON, or
       | have some converter from JSON to NGINX config.
        
         | supriyo-biswas wrote:
         | nginx unit[1] has JSON configuration. Although it's not
         | terrible to write a hand-rolled recursive descent parser.
         | 
         | [1] https://unit.nginx.org/configuration/
        
         | mmsc wrote:
         | crossplane is an nginx<-->json converter:
         | https://github.com/nginxinc/crossplane
         | 
         | It works well, but probably doesn't solve your actual problem,
         | because it still uses nginx _format_ -- just in json:)
        
         | MathMonkeyMan wrote:
         | Nginx's configuration is the most flexible I've ever seen. When
         | writing an nginx module, you have a handle to the config file
         | being read, and you can do whatever you want. Conventions of
         | syntax really are just conventions. There's no grammar.
         | 
         | I'd prefer a formal language with a parse tree and all that,
         | but I think the spirit of the nginx code is "just what you need
         | and nothing more."
        
         | defanor wrote:
         | As a counterpoint, I find custom formats to often be nicer than
         | reusing generic ones: atomic values (individual lexemes,
         | primitive types: strings, numbers, etc) tend to have custom
         | formats or semantic restrictions anyway (say, dates, length-
         | limited strings, range-limited numbers, though in some cases
         | numbers are also just restricted strings), so that part is
         | mostly handled from scratch either way. And then there is
         | composition, with JSON--apparently the most popular format now
         | --not having a standard way to encode sum types, so you
         | basically have to hammer those on top. At which point it feels
         | like building on top of a JSON structure instead of building on
         | top of a sequence of characters, but not in a very different
         | way: sometimes it is more helpful in some parts, sometimes adds
         | more clutter than needed. Likewise with XML: it is not uncommon
         | to see something like <my-custom-format>a string in a custom
         | format here, or even a base64-encoded blob</my-custom-format>.
         | 
         | In practice it is easier to use JSON for interfaces, since for
         | someone unfamiliar with parsing it is less work to sort out on
         | the other end, and then you have at least a partially specified
         | structure, the rest can be easier to specify (with JSON schema,
         | for instance), there are readily available libraries and tools
         | to work with it, to do at least some of the parsing without
         | writing a parser. But I think cleaner interfaces can be
         | achieved with custom formats.
        
       | efxzx wrote:
       | Great tool! Also, what about apache2, any similar tool
       | suggestions?
        
       | alp1n3_eth wrote:
       | Would it be useful or easier to plug in if these were rules
       | developed for platforms such as Semgrep? It looks like they
       | already have an existing nginx ruleset:
       | https://semgrep.dev/p/nginx.
       | 
       | They can always use some extra contributions, and would slot into
       | existing tooling within a pipeline.
        
       | ajayvk wrote:
       | I have been building a platform [1] which makes it easy to deploy
       | internal tools. Instead of taking the config file approach, it
       | allows you to install each app at a unique location (domain name
       | + url path). Within its location, the app owns all the URLs and
       | can managing request routing without requiring a global config
       | update.
       | 
       | The advantage is that new app installations cannot interfere with
       | an existing app. I wrote more about this approach at
       | https://clace.io/blog/webserver/
       | 
       | [1] https://github.com/claceio/clace
        
       | ProfDreamer wrote:
       | Using the nginx module on NixOS[1] and enabling
       | services.nginx.validateConfigFil, which defaults to true,
       | generated nginx configurations will be checked by Gixy[2]. The
       | build will actually fail if Gixy finds any issues.
       | 
       | [1]:
       | https://github.com/NixOS/nixpkgs/blob/nixos-24.11/nixos/modu...
       | [2]:
       | https://github.com/NixOS/nixpkgs/blob/nixos-24.11/pkgs/build...
        
       ___________________________________________________________________
       (page generated 2025-02-16 23:01 UTC)