[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)