[HN Gopher] Nginx Unit - Universal web app server ___________________________________________________________________ Nginx Unit - Universal web app server Author : promiseofbeans Score : 516 points Date : 2023-09-10 08:10 UTC (14 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | jchook wrote: | Nginx Unit + PHP seems to handedly out-perform Nginx + php- | fpm[1][2][3]. | | Also, Docker environments running PHP via Nginx Unit will no | longer need separate containers for http + fpm, as it works | similar to Apache's mod_php. | | 1. https://habr.com/en/articles/646397/ | | 2. https://medium.com/@le_moment_it/nginx-unit-discover-and- | ben... | | 3. | https://github.com/nginx/unit/issues/6#issuecomment-38407362... | tiffanyh wrote: | Two questions: | | 1. Does Unit + PHP doing the typical "initialize & teardown" | that PHP is know for? | | Or is Unit persisting the initialization/setup, hence why it's | achieving the way faster results? | | 2. How is Unit/PHP architecturally different than NGX-PHP (an | event loop)? | | https://github.com/rryqszq4/ngx-php | Dachande663 wrote: | PHP's had an opcache and jit for several versions now. | Combined with preload options, this means startup time is | negligible. | conradfr wrote: | You don't need separate containers to run nginx and php-fpm. | kobalsky wrote: | does it involve running supervisor inside the container? | that's fine but it's definitely not kosher. | | in my experience those are the ones that kick and scream when | they don't start as root. | conradfr wrote: | php-fpm & nginx -g "daemon off;" | [deleted] | wongarsu wrote: | Are you implying that docker containers don't run a unikernel | that can only run one application at a time? /s | martinsnow wrote: | I too would like to see a properly configured php+php-fpm | container benchmark. There's a lot of overhead when you link | by http instead of a unix socket, in the same container. | e12e wrote: | Technically, you should be able to share a domain socket | via a shared volume too (between an "app" and "web" | container) - as with postgres: | | https://github.com/sameersbn/docker- | postgresql/issues/30#iss... | | Curious about benchmarks and tests of TCP vs Unix domain | sockets between docker containers. | ComputerGuru wrote: | Those benchmark outcomes are ridiculously in nginx-unit's favor | over php-fpm, way more than I would have believed was possible. | What is php-fpm doing architecturally that is so different to | warrant such poor relative performance? | pbowyer wrote: | You see similar performance improvements in bencharmarks of | Litespeed & PHP LSAPI [1]. | | Unfortunately said benchmarks are usually done by the | software company making said webserver, so have to be taken | with a pinch of salt. | | 1. https://www.litespeedtech.com/open-source/litespeed- | sapi/php | jiggawatts wrote: | This seems a lot more like how IIS works, unless I'm missing | something? | | As an aside: it's always curious to see how the programming world | has splintered into cliques that no longer hang out together. | | NGINX Unit is a "Universal" web server without support for C++, | Rust, or ASP.NET! | | But _PERL_ is supported, like the 1990s Linux cgi-bin world never | went away. | coldtea wrote: | In Linux where this is primarily expected to be used ASP.NET is | extremely rare, as is C++ for web stuff, and Rust has a | vanishingly small web presence still. Lots of people use Perl | still though, if not for anything else, for legacy stuff. | | So might as well ask why it doesn't support Delphi. | jddj wrote: | Do you have data for your asp.net Linux claim? Feels | anachronistic. | pseudosavant wrote: | This is anecdata, but my experience with modern ASP.NET | teams these days is that while production may still be | running Windows, the dev teams are a mix of Mac, Windows, | and Linux/WSL. The allure of the M2 MBP is too great when | the Windows option is an expensive but otherwise | forgettable Dell corporate laptop. | ComputerGuru wrote: | I can't say I know the percentage of Linux servers running | ASP.NET Core but the percentage of ASP.NET Core apps running | on Linux is no longer negligible. Bing runs it on Linux, | iirc. | | This isn't the dark days of .NET Framework anymore. | mst wrote: | And PSGI is actually really rather good (for sync stuff, I | dislike the way it handles async/websockets and would tend to | use Mojolicious for that) and generally used to deploy OO MVC | style apps. | | The Perl ecosystem has come a long way from CGI scripts just | like everybody else has. | crvdgc wrote: | Don't know about ASP.NET, but one of the supported languages is | assembly, so I'd presume C++ and Rust can easily add a wrapper | around that. | | > Binary-compiled languages in general: using the embedded | libunit library. | | From https://unit.nginx.org/keyfeatures/#supported-app- | languages | tyingq wrote: | Reads like it's not real straightforward or well documented | for rust: | | https://github.com/nginx/unit/issues/738 | mbreese wrote: | And Go apps require recompiling them to use their version of | the http. ListenAndServe function. I'm not sure if this counts | either... | | https://unit.nginx.org/configuration/#updating-go-apps | sethammons wrote: | And requires you to enable CGO, which I avoid at all costs if | I can | mindwok wrote: | Well I commend the Nginx team for trying something new and | launching this, even though I'm not sure what I would use it for | personally. | | Slightly tangental, but it always irks me when I see these kinds | of responses in JSON: { "success": | "Reconfiguration done." } | | Really this should be something like "result": "success". Using | "success" as a key name tells me nothing about the data it's | representing. | giancarlostoro wrote: | I rather have: | | { "responseMessage": "Reconfiguration done.", "responseCode": | 133, "isSuccessful": true } | | This way you can map to a custom message on your front-end | based on the responseCode whether its successful or not, you | can fallback to the response message if no mapping is found, | and you can easily check if the transaction was successful or | not. | dan-robertson wrote: | I think this is trying to be a discriminated union type[1] in | json. One way to do it is to have a 'tag' field that says "ok" | or "err" or whatever and then other fields for the rest of the | data (or an array with the tag in the first slot). Another is | to have one field whose name is the tag and whose value is | everything else (which is what happened here). | | [1] eg one where the possible values are either Err(<some | error>) or Ok(<some result>), and the data inside could be more | complex types instead of just strings | tecleandor wrote: | That's like when I see APIs that give you responses with a 200 | code, but then in the message there's a backend error. | smashed wrote: | Some people treat http as a pure transport/network layer and | the actual body as the app-level layer. | | In such an approach, any http-level error would be a network, | server maintenance or other unknown/fatal error type of | things. | | App errors are encoded in the response body in a app-defined | way. | | It's not a completely bogus way of handling things, as long | as it is perfectly consistent throughout the project and | properly documented, which is rarely the case. | FridgeSeal wrote: | Looks pointedly at graphQL projects. | wruza wrote: | The opposite of that is people who try to loosely project the | variety of error modes their app has to http status codes. | You then print out a table of http code <-> actual meaning | and try to outline ranges and messages you want to handle | differently. On top of that, their backend may be down and | you have to deal with bare reverse proxy statuses as well, | which adds another dimension to that mess. | tanepiper wrote: | Regarding use case. We have a bunch of frontend apps that are | integrations to one of our external platforms - they get hosted | in an iframe on there. | | To simplify the builds we have a expressjs app that is a simple | static server and proxy for API requests. | | I can see something like this easily replace that - all we need | is static files and a /API* endpoint to proxy - avoiding cors | issues. | 9dev wrote: | Heh. My pet peeve are useless success fields. A 200 response | tells you it was successful already. We can talk about a | ,,message" field or something if you intend to display it to a | user, but even that should be implicit by being a response to a | specific request. If I send a POST /configuration, is there | really something new to be gained from that message that the | client cannot figure out on its own? Wouldn't, perhaps, a 201 | No Content suffice? | eterps wrote: | Eric S. Raymond, in his guide "The Art of Unix Programming", | mentions this principle as Rule of Silence: "When a program | has nothing surprising to say, it should say nothing." | | His statement probably related to command line applications, | but it makes sense for a lot of cases. | pydry wrote: | It sounds smart but what counts as surprising is entirely | context dependent and most programs won't be aware of your | context. | | E.g. a command line app where you put a subtly wrong switch | in that does exactly what it thought you wanted and prints | nothing while outputting a 0 exit code is dangerous. | couchand wrote: | It's about context, of course, but it's not really the | program's responsibility to know the user's context. It's | the user's responsibility to understand their own | context. | | A tool should have sufficient interlocks to ensure safety | when not engaged, but no more. | loloquwowndueo wrote: | What, like rm -rf ? | 9dev wrote: | I follow your point, however it actually supports mine: | An HTTP response isn't intended to be the output of a | command line app. A command line app should take the | response from the lower-level HTTP communication and | articulate whatever appropriate message to the user, | depending on the verbosity level for example. Talking in | OSI terms - this is a presentation layer problem, not a | link layer one. | laserDinosaur wrote: | "When a program has nothing surprising to say, it should | say nothing." | | Which sounds good in theory, until you run into issues like | this: https://www.youtube.com/watch?v=tLdRBsuvVKc | | TLDW: Most of the Gitlabs outage where they deleted the | primary prod and backup prod database could have been | solved if they just waited for the command line op to | complete - but because of a lack of feedback they thought | it had frozen, leading to several other plans which made | the situation worse. | asmor wrote: | Unit has been around for half a decade. It feels like an | evolution to something like Phusion Passenger, but it's not | quite cloud-native. A lot of the documentation is tailored to | installing directly on a server and some essentials (i.e. | prometheus metrics) are missing. | | I briefly evaluated it for bringing a PHP team into our | Kubernetes cluster, but then ended up writing a bit of Go code | to proxy into a real nginx+fcgi while adding a syslog sink (so | PHP could log to stdout/stderr) and our standard prometheus | metrics on the Go http server. | fideloper wrote: | wait, did that continue to use php-fpm? if not I want details | plz! :D (especially around the logging sync, unless it's just | php-fpm configured to collect child process output) | asmor wrote: | Yes, it did, not too much magic going on, the Go proxy also | was a replacement for supervisord so it started nginx and | fpm, reaped zombies and pulled all the important logs into | stdout/stderr. The most remarkable thing was how this | revitalized a team that wrote boring PHP software limited | to deploying via FTP on PHP 5. | | They ended up really getting into stripping out every piece | of PHP they didn't use because the image built PHP from | scratch, eventually took over maintenance of the go piece | and ported a bunch of their apps to Symphony. I was in a | platform engineering team and they were one of the few | teams to really torture test every feature we ever shipped | to the point they'd report edge cases or a bug to us every | other week or so. | | As for the logging question, we configured Symphony to log | to syslog, which was provided by the Go daemon via unix | socket. | fideloper wrote: | awesome, thank you for the details! | afavour wrote: | If I were designing it I'd probably have a result field too, or | even a success boolean. But I don't hate what they're doing | here: the presence of the key is the Boolean value, the value | is the description. A two for one. | wruza wrote: | An economy not worth investing in in my book. It's always | more clear to separate success and result. Sometimes, you'll | have no result, so there will be some parasitic (or truthy) | value like null or true. And when you check success-named | result deeper/further in code, it looks like you're indexing | into a boolean. Trying to make it clear on-site creates | miniprotocols not worth remembering. Worst case scenario is | {success:x, error:y}, x and y being 4 combinations of null | and non-null, where you aren't even sure what happened and | may swallow a false positive with an optimistic check. Also, | since undefined is not in json standard, the existence | becomes ephemeral in languages where that's distinct from | just being undefined. You may think that returning undefined | from a wrapped worker is okay, but it results in "error | encountered: undefined" down the line due to {} payload. It's | one of the things that make programming harder for no good | reason. | chrismorgan wrote: | In this _particular_ example, it's actually a whole lot worse | than that, by spec at least. Excerpt from their OpenAPI schema | <https://github.com/nginx/unit/blob/7dd5ad93a4c147b086a8d82ec.. | .>: jsonSuccessMessage: type: | object description: "JSON message on success." | additionalProperties: type: string | jsonErrorMessage: type: object description: | "JSON message on error." additionalProperties: | type: string | | Yes, this is as bad as it looks: _"success" isn't even part of | the schema_. It's in the _examples_ , but not the actual schema | definition. The way success or failure is _actually_ indicated | is by HTTP status codes. 200 is success, 400 /404/500 is error. | So, they seem to set very bad precedent in at least one of | their response and their schema. | | But I was expecting it to be something like {"success": string} | | {"error": string}, which is frankly a perfectly reasonable | way of doing things: an untagged, but still unambiguous, union. | It can make for quite pleasant code, too: `if response.success` | and such. | | You're looking for a tagged union, something like {"result": | "success" | "error", "message": string} (or alternatively like | {"result": "success", "message": string} | {"result": "error", | "code": string, ...}), which is also a perfectly reasonable way | of doing things. In some ways it can be viewed as more | principled, as it _more formally_ allows you to check the tag. | | Really, the two approaches are much of a muchness. They each | have their strengths and their weaknesses. But if general | status is being done at the HTTP layer, I'd prefer {"message": | "Reconfiguration done."}, or... well, actually, just a 204 No | Content response, and no JSON or body at all. | | (On the terms untagged and tagged unions as I'm using them: | they're necessarily a bit different from the concepts as | exposed in languages like C, since you're dealing with a model | built on objects rather than bytes, but they're still | reasonable descriptions of them. In Serde's classifications, | they'd be the untagged and internally tagged enum | representations <https://serde.rs/enum-representations.html>.) | thibaut_barrere wrote: | > Yes, this is as bad as it looks: "success" isn't even part | of the schema. It's in the examples, but not the actual | schema definition. | | Having gone through a pretty heavy overhaul of an "OpenAPI" | (full code in Elixir at https://github.com/etalab/transport- | site/pull/3351), I stumbled on that exact type of problem! | | At the scale of nginx, having automatic verification that the | examples (and the output of the API in general) match the | specification would be great. | | At our scale, here is what really helped me go through the | rework (and ensure we do not regress too easily): | | - setting additionalProperties to "false" to detect key field | "rot" | | - using "required: [x,y,z]" on everything, and by default | specify "all the property keys", with an opt-out (so that | each time a developer adds a field later, it is considered | mandatory, unless otherwise specified) | | - use tooling during the tests: "assert_schema" (with | OpenAPISpex) to ensure our API endpoints responses pass the | spec (additionalProperties: false helps ensure we get an | exception in case of key field rot, again!) | | - even more useful: crawl our production most important | endpoints and tweak the spec until everything is green (an | example of useful use of Task.async_stream in Elixir, by the | way) https://github.com/etalab/transport- | site/pull/3351/files#dif... | | It can be super frustrating for users to live with the | uncertainty of the response of an API for sure, and I was | happy to discover the Elixir tooling (OpenAPISpex in | particular) worked so nicely once I understood what I had to | do. | tough wrote: | I recently found this open source postman typed | alternative, hadn't had time to really try it yet but the | types stuff should help here no? | | https://recipeui.com/ | thibaut_barrere wrote: | The type support in OpenAPI is fairly good (enough for | us), and using a tool directly built on our stack allows | nice things. | | Thanks for the link though! | usrusr wrote: | Looks like the openAPI is a little rough around the redundant | status fillers? Wouldn't be the first one I guess. | | Putting the redundancy with 200 or not 200 aside, I sense a | certain aesthetic quality in the | {"success":string}|{"error":string} approach. Namely in how | it adheres to keeping the schematic stuff on left side of the | colon. | Nullabillity wrote: | By Serde's classification, `success: {}` is a textbook | _externally tagged_ representation. | chrismorgan wrote: | If there was always only one top-level field and everything | else was inside that, it could be externally tagged, but | it's definitely just untagged here, because | #/components/examples/errorInvalidJson/value (line 4397) | shows an error body with multiple top-level fields: | {"error":"Invalid JSON.","detail":"...","location":{"offset | ":0,"line":1,"column":0}}. Externally tagged would be | {"error":{"message":"Invalid | JSON.","detail":"...","location":{...}}}. | mindwok wrote: | I wasn't familiar with Serde's description of this so that | was a good read, thanks. | | Although I still think this is a bad example of an | externally tagged representation. In the Serde example they | have the key as "Request" then what follows is the request | object. In this example, the "success" key is followed by | an arbitrary string message, which isn't obvious at all. | Nullabillity wrote: | The contents of each variant don't really matter here. | The tag represents the variant, not the type contained | inside of it. The Serde equivalent here would be: | #[derive(Serialize, Deserialize)] | #[serde(rename_all = "camelCase")] pub enum | Response { Success(serde_json::Value), | Error(serde_json::Value), } | [deleted] | maxloh wrote: | Why including that in the response body? 200 status code states | everything. | revskill wrote: | Should it be | | { status: 200, body: { "message": "Reconfiguration done." } } | | ? | KronisLV wrote: | Hey, this is pretty cool to see! | | Here's a page with the features: | https://unit.nginx.org/keyfeatures/ | | The languages supported, if anyone is curious: | Binary-compiled languages in general: using the embedded libunit | library. Go: by overriding the http module. | JavaScript (Node.js): by automatically overloading the http and | websocket modules. Java: by using the Servlet Specification | 3.1 and WebSocket APIs. Perl: by using PSGI. PHP: by | using a custom SAPI module. Python: by using WSGI or ASGI | with WebSocket support. Ruby: by using the Rack API. | WebAssembly: by using Wasmtime. | | I'm currently using Apache as a reverse proxy for most apps and | sometimes PHP-FPM when I need to run software with PHP, which | works well for my personal needs (mod_md and mod_auth_openidc are | pretty cool), but it's cool to see something similarly | interesting to OpenResty coming along as well, too! | vcryan wrote: | For a NodeJS app, could you remove something like nodemon by | using this? That could make this appealing. | amiga-workbench wrote: | You can replace nodemon/PM2 with a systemd unit file. | Dachande663 wrote: | Tested this with a moderately complex PHP Laravel app and got a | 40% speed improvement. Very useful to be able to run multiple | apps each using different lang runtimes/versions without needing | separate docker containers. | dieulot wrote: | 40% improvement versus what? A docker container for nginx and | another one for PHP? | Dachande663 wrote: | Compared to nginx and PHP-FPM installed on a host machine. | All running opcache, JIT etc. Was pleasantly surprised. Note | this is up to 40%, not all apps we've run have seen same | improvement. | [deleted] | sidcool wrote: | What were you using earlier? | quickthrower2 wrote: | Sounds like a blog post in the making | husarcik wrote: | How does this speed improvement compare to Laravel octane with | swoole? Curious if I can switch! | Dachande663 wrote: | We tried roadrunner (similar thing), but couldn't do it | without rewriting certain bits of the app (anything with | globals basically) whereas unit was a straight swap. My guess | would be, if you're properly using the advantages swoole can | bring (like shared memory cache etc), it will outperform | unit. | talboren wrote: | YAWS - yet another web server | e12e wrote: | 2017? | | https://youtu.be/I4IWEz2lBWU | akokanka wrote: | Yeah welcome to NgineX universe, hence I still prefer Apache | httpd | tomjen3 wrote: | This is an interesting idea, but I feel like it is a big | oversight not to have build in support for automatically getting | certificates. | | Instead the docs have you do something manual with certbot (a | complete nono if you believe in automatic SSL and are using | docker images that don't persist data, as Docker is meant to be | used). | | The only reason I have SSL on my domain in the first place is | that my host offers a simple setup that runs automatically. | _joel wrote: | > using docker images that don't persist data, as Docker is | meant to be used | | docker volumes entered the chat | tomjen3 wrote: | Which means now you can't do a clean deploy of a new version, | you can't be sure that what works on one machine is the same | as what works on another etc. | ComputerGuru wrote: | Can you feasibly run this behind nginx (either over http in a | regular reverse proxy setup or with sort of more clever shared | memory forwarding situation?) so you could, eg use nginx-unit | instead of php-fpm but keep everything (ssl termination, rate | limiting, etc) centralized behind your core nginx load balancer? | | Edit: yes, it's as straightforward as it sounds: | https://unit.nginx.org/howto/integration/ | ojintoad wrote: | excited for .NET support so I can write NUnit tests verifying my | NGINX Unit hosted software | CodeCompost wrote: | Looks like this is more focused on ease of use rather than | bringing new features in. | DarkCrusader2 wrote: | > open source server project that works as a reverse proxy, | serves static assets, and runs applications in multiple | languages. | | Isn't this what Nginx also does. How is Nginx Unit different | beyond configuration via JSON REST APIs? The Github readme or | their site is not very clear on this. | pacifika wrote: | Nginx doesn't talk to Python or php directly it's talks to the | application server. | stefantalpalaru wrote: | [dead] | dmarinus wrote: | this is a nice alternative for the apache php module (mod_php) if | you don't want to or can't use php-fpm. | yetanother-1 wrote: | Would you prefer this over Traefik for a simple docker-compose | setup? | Grimburger wrote: | > a simple docker-compose | | Abstraction at it's finest. | 9dev wrote: | What strikes you as difficult with compose files? In fact, I | would say it's the most concise format to describe a desired | state of running applications currently available. | Grimburger wrote: | Nothing is difficult about them, compose is easy enough | that you can grok it in a day. | | You saw the lament in my comment though and that speaks a | deeper truth. | | If WSL took off quick enough we could have had lxc as the | main player rather than the bastardisation of lxc that is | docker.com | | For an open source project they make it incredibly hard to | access what are essentially text files for containerisation | setups on windows or mac? | | https://github.com/docker/hub-feedback/issues/1103 | 9dev wrote: | Compose is an open source project entirely separate to | hub, though. The compose file specification is versioned | separately, and will outlive Docker, probably. So I don't | quite get your criticism? | Grimburger wrote: | How are you using compose without docker? They are joined | at the hip, criticism of one is criticism of the other. | | The days of cheap money are over, it's inevitable that | certain SaaS companies will start tightening the screws | on their users to match the returns they can get with | cash in a bank. I just wish lxc (which docker was built | off) got a chance to gain traction. It's miles ahead in | DX and sure they serve different functionalities but can | be used the same and the network effects can't be | understated. | notpushkin wrote: | Unironically this. After trying Kubernetes, Terraform, | Ansible, and various proprietary PaaS config formats, I've | grown to love Compose files' simplicity. | segfaltnh wrote: | Yes, when compared to extreme complexity, compose is | simpler. But it's hardly simple. | notpushkin wrote: | I'll happily try anything simpler than that if you give | me an idea what that might be. | | Not trying to be salty or anything - I really think | Compose hits the sweet spot of abstraction which is less | complex than both the monstrosities I listed and the _ad | hoc Bash scripts copying code over SSH and restarting | services_ approach (so, the other extremity of | declarative v. imperative). | ljm wrote: | I didn't think I would see traefik and simple in the same | sentence. | fideloper wrote: | I was just playing with this the other day. | | Trying to find context on what it was, I saw it's been on HN a | few times (mostly to the sound of people asking the same | question). | | Since I mostly do php/laravel, I was pleasantly surprised that it | let me remove php-fpm from my stack - extremely nice when putting | PHP apps in a container. | | I personally have come to dislike PHP-FPM's max_children and | similar settings, whose low defaults come as an annoying surprise | when you suddenly get gateway errors before your server is even | overloaded. (and having to add nginx AND php-fpm "layers" into a | container to run PHP apps is all sorts of annoying). | | Unit doesn't have as many features as Nginx so I suspect it's | best used when there's another fully-featured http layer in front | of Unit (to more easily handle TLS, protecting dot files, gzip, | cache headers, and the like). | | Overall i'm excited to use it when making images for php apps. | tandav wrote: | If you need just reverse proxy, Caddyfile syntax looks simpler: | myapp.company.com { reverse_proxy localhost:3000 | } | logeist wrote: | Came here to say Caddy still seems like the way to go for most | use cases. Although I don't use it in any 'prod' environments | it checks all the boxes. | mirzap wrote: | What is the difference between Nginx and Nginx Unit? Benefits? | jalk wrote: | Nginx-unit is reconfigurable using REST: | https://unit.nginx.org/controlapi/ | usrusr wrote: | So much JSON... is that the real thing, as in comments are the | gateway to hell, or is it actually some practical JSON superset | like JSON5? | | I almost see myself jury-rigging some bespoke filesystem on-ramp | to that REST configuration interface. Likely with at least half a | dozen scary security compromises. | | Then on the other hand I guess they've never been afraid of | getting called opinionated and that's certainly much better than | trying to be everything, for everyone, at the same time. | gjvc wrote: | JSON without comments is hell, forcing one to 1) convert JSON | configuration to YAML. 2) add comments to YAML and admire it. | 3) convert YAML to JSON for sending to the server. | coldtea wrote: | YAML is an order of magnitude more hell... | sethammons wrote: | I literally cannot count the number of times significant | whitespace has broken a yaml file I've edited followed by a | completely useless error on line 1. I don't have this | problem in python. I loath yaml. | johnchristopher wrote: | But TOML is worse, right ? I can't write nor read TOML to | save my life... :( | rascul wrote: | TOML is much simpler in general but it does have its | warts. It's basically just key = "value" pairs in | [sections] for the simple stuff. | coldtea wrote: | I think it's saner, but still has some bizarre design | choices | usrusr wrote: | Fortunately it's only forcing one to convert to a JSON | variant that does not forbid comments (starting as simple as | wrapping the entire thing in console.log JSON.stringify). | I'll happily leave the YAML authoring to YAML inventors, | supposedly it makes them happy. | otterley wrote: | I like to think of JSON as a low-level configuration language | that most people should generate from a higher-level language | such as Python or JSONnet -- sort of like assembly is to C. | JSON has lots of things to like about it, but I don't recommend | generating it manually for most people for files larger than a | few lines. | [deleted] | gibmeat wrote: | Why the obsession (it seems to be the prominent point in the | readme) with configuration via API? How often do you need to add | php support on the fly? I want to configure my app server via | files so it just starts up in the state that I expect. What am I | missing? | gabereiser wrote: | Why? To scale infra of my offering to my customers. They need | it too. I'd like for my remaining customers to not suffer | downtime. I'd like to use the existing infra I have without | spinning up new ones. I'd like to offer a dashboard so my | customer can configure their host. | fragmede wrote: | > How often do you need to add php support on the fly? | | Restarting the binary means you'll lose requests while it's | restarting, so adding php (or whatever) support on the fly is | what you need when running a system where losing those requests | is material. Which it won't be for most people, but for, eg, | Google (who don't use Nginx), losing those requests is a | problem. | 22c wrote: | Although it doesn't directly go against what you're saying, | many Unix daemons have supported HUP signals for decades | which can achieve the same outcome. No need to configure via | API, just change the configuration on disk and send HUP. | | I suppose arguably that becomes a bit trickier for | containers, so perhaps that's why you'd want to configure via | an API? | hamandcheese wrote: | To me this is identical - mutable state is mutable state, | whether it starts on disk first makes no difference. | hamandcheese wrote: | Any half decent containerized setup should support zero- | downtime deploys. Usually it involves bringing up new | containers and signaling the existing containers to begin | draining connections. | | For most workloads it should be entirely possible to deploy a | new stateless config and not need to resort to using mutable | state for critical infrastructure. | | If you have long-lived, stateful connections (perhaps for | live streams) then I can see why re-configuring in place | would be desirable, but in my experience that's pretty rare. | xorcist wrote: | Neither Apache nor nginx require a restart to add php | support, and neither will lose requests under normal | operation. They will however parse the complete config on a | reload operation. On huge configurations this is noticeable. | didip wrote: | For webapp, maybe not very valuable. | | But for API gateway or any kind of sidecars? Very valuable. | ramesh31 wrote: | >Why the obsession (it seems to be the prominent point in the | readme) with configuration via API? | | Infrastructure As Code (in all its forms, | chef/puppet/ansible/tfe etc.) is the standard for all | enterprise cloud setups these days. It makes sense to support | that as a first class feature. | shawabawa3 wrote: | but this is the opposite of infrastructure-as-code | | This is infrastructure-as-state | | You have to manage automatically loading configs and keeping | in sync with what you have in code, instead of deploying with | a static configuration file | notnmeyer wrote: | it's not hard to imagine a use case where there are backend | configurations stored in a database somewhere and you want | to apply them. i'm picturing it as data vs static | configuration. | jen20 wrote: | Perhaps adding support for PHP on the fly is an extreme case, | but reconfiguring eg load balancer backends when new systems | come and go without having to render a config file and HUP (and | hope) is a typical case. | indymike wrote: | If the state you need at startup isn't the same as you need for | production, this could be incredibly useful. It also means that | you can save a lot of time starting and stopping containers for | many common configuration changes in production. There's a lot | more utility in this than just PHP. | sneak wrote: | This allows you to start up generic machines with no | configuration and customize them after boot from a remote host. | | It's not so much "on the fly", as it is moving the long-term | config storage to a different system. | remram wrote: | I don't buy it. For this situation I would much rather have | the software load its (regular) configuration file from a | URL. | Ayesh wrote: | Probably the most common use case is SaaS providers that | support custom domain name for whatever the software it is. For | example, a site uptime monitoring service might offer a feature | to host a status page on a custom (sub)domain of the customer. | The SaaS now needs to programatically create virtual hosts on | demand, issue HTTPS certificates, run routine updates, etc. | | An API and a web server with small segmented updates make this | so much easier. Compare this to Apache, that has to wait to | properly end existing connections before reloading, has a | config file parsing overhead, and probably does not scale that | well with several virtual hosts anyway. There are hardware/File | System level limitations as well. | ExoticPearTree wrote: | This seems to be a "universal" app server, like gunicorn is for | running Pyhthon stuff, php-fpm for PHP and so on. | | It was first launched as closed source and the marketing | gibberish f5 came up with made it sound like make believe. | [deleted] | ghoshbishakh wrote: | This is really interesting. Wonder how does it compare to tomcat | or undertow for Java | ilovefood wrote: | This is really great! What I'm really look forward to trying is | the server side WebAssembly: | https://unit.nginx.org/configuration/#configuration-wasm. | | Huge potential! | eterps wrote: | What specifically are you looking forward to? | ilovefood wrote: | I've been tinkering quite a bit with WasmCloud and WasmEdge | lately, for some data workloads (scraping, ingesting, apis | etc) mainly as an excuse to learn WebAssembly. | | What I want to see for myself is how Unit compares to those | for this reduced scope (api's/services) and how fast I can be | productive with it. This could be a good starting point for a | lot of new applications, kind of an "airflow (the data | orchestration thing) on Webassembly". | | So main points are performance (is it good enough) and | developer experience (is it easy to maintain/change). | | Nothing really ground breaking, just trying out stuff. | drawfloat wrote: | What's the advantage of server side WebAssembly over just | running a Rust/whatever application? | pseudosavant wrote: | Security isolation too. I am using a WASM-based image | processing pipeline for handling user submitted images. Much | safer than trying to run a binary (Imagemagick, ffmpeg, etc) | written in an unsafe language. In my case, the WASM does not | have access to anything outside the sandbox. | imhoguy wrote: | Have you compared how much performance overhead has such | sandbox in comparison to native (Linux) binary? Especially | video processing. I just wonder if WASM app can even | benefit from SSE4 or AVX instructions. | politelemon wrote: | My limited understanding from various blog posts is that you | can still get the benefits of a container, but much faster | startup/runtimes. As in WASM provides performance very close | to native. | sideeffffect wrote: | It even supports Scala (Scala Native, that is) | | https://github.com/lolgab/snunit | spoiler wrote: | I only glanced at the docs, but way they expect apps to integrate | with it seems a bit convoluted to me? It's not really a reverse | proxy at this | | What would be wrong with just using HTTP/2, maybe with a few | custom headers sprinkled in for custom features? | TheHappyOddish wrote: | > It's not really a reverse proxy at this | | In fact it's not one at all, nor does it claim to be. It's an | app server. | cxcorp wrote: | > NGINX Unit - universal web app server - a lightweight and | versatile open source server project that works as a reverse | proxy, serves static assets, and runs applications in | multiple languages. | | https://github.com/nginx/unit | layer8 wrote: | They should make a page explaining how this differs from Nginx | and why it needs to be its own separate thing. I couldn't find | such a page. | bewuethr wrote: | Here maybe? https://www.nginx.com/products/nginx-unit/ | slim wrote: | does not answer the question | bewuethr wrote: | I feel like the section "How Does NGINX Unit Compare to | NGINX Web Server?" does answer some aspects of it. | [deleted] | l5870uoo9y wrote: | Thought for a second that it included automatic TLS certificates | but that is still done manually with Certbot, which also isn't | that difficult. | danappelxx wrote: | Not that difficult, but it's still a separate dependency (with | python requirements). If the goal here is a Caddy competitor, | then IMO it's missing the mark in terms of "one stop shop". | What's the killer feature? | wolletd wrote: | On the python requirements: I've always been satisfied with | Bash implementations of ACME. I use dehydrated from the very | beginning (when it was still called letsencrypt.sh) and | lately started using acme.sh. | kijin wrote: | This thing will probably run in a bunch of VMs/containers | behind a load balancer, so it's actually better that it doesn't | try to obtain any certificates by default. | | Even a small number of apps trying to get their own | certificates at the same time can exhaust the Let's Encrypt | quota for your domain, with serious consequences to your other | online properties. | smarkov wrote: | > Even a small number of apps trying to get their own | certificates at the same time can exhaust the Let's Encrypt | quota for your domain | | I got curious about this and decided to look it up, they | actually have more restrictions than I expected[1]. Looks | like to play it on the safe side you might be better off | having a single server issuing certificates and distributing | them where needed as well as using wildcards as much as | possible. Interestingly, it looks like Google is doing just | that since their certificate covers a very wide range of | domains[2]. | | [1] https://letsencrypt.org/docs/rate-limits/ | | [2] https://www.sslchecker.com/sslchecker?su=b39e88e1c4d3efcd | b79... | [deleted] | smetj wrote: | Finally something exciting! If only this had event push | capabilities usefull for discoverability and announcement | patterns over various sinks http/nats/mqtt/amqp ... | vinay_ys wrote: | It is a great start and shows very good potential. Still need to | build support for io_uring, and all the sundry features in | mainline nginx, apache, haproxy etc. | lagniappe wrote: | I built something like this, but with much simpler syntax and | automatic https simply bc I'm not smart enough to reliably set up | server blocks and letsencrypt every time I route a new app. | | AppServe takes care of all that, and even if I did know the | syntax by heart to do it in nginx, this is still faster. | | https://github.com/donuts-are-good/appserve | Matl wrote: | Nice, that being said if the concern is complex config, there's | always Caddy[1]. | | 1 - https://github.com/caddyserver/caddy | lagniappe wrote: | AppServe gets compared to Caddy a lot, which is very | flattering, so thank you :) Caddy's good stuff! | Ranked6815 wrote: | I choose envoy | fulafel wrote: | There seems to be code in several languages - are the parts on | the front lines of untrusted input written in some memory safe | language? | whatever1 wrote: | So for a python django project this would replace gunicorn? | winrid wrote: | I would also like to know this. | | Edit, yes: https://unit.nginx.org/howto/django/ | [deleted] | abdellah123 wrote: | I'd love to see a performance benchmark for unit. Especially for | an nodejs/express app | donatj wrote: | I remember when they announced this a couple years ago I had no | idea why I would use it over standard nginx. That seems to still | be the case. | | It's JSON controlled via Curl? And has a bunch of langue's built | in for some reason? The question becomes why? | pseudosavant wrote: | This is the question I keep asking myself as I read more. Why? | | Only the NGINX team would think to "simplify" loading a | configuration file from the CLI by using curl to post it. | smh... | vanjajaja1 wrote: | I like it, has potential to push docker out of the application | layer | andrewstuart wrote: | I switched to caddy from nginx and didn't look back. | | Auto SSL wildcards was enough. | tacker2000 wrote: | How is Caddys performance compared to nginx? | mholt wrote: | It's very good. In some cases better. For example Caddy can | handle tens of thousands of certs without problem whereas | nginx + Certbot would choke. | | The difference is negligible to most people. | MrStonedOne wrote: | [dead] ___________________________________________________________________ (page generated 2023-09-10 23:00 UTC)