1. 37
  1.  

  2. 7

    :D i just want to take the opportunity to say that seeing my little post inspire things like this fills me with joy. i adore how you handled post content, especially the includes & img embeds - very clever! love it. your code was very fun to read through. ty for sharing. :3

    1. 7

      Thank you for the post you’ve submitted, it was your cool idea in the first place. Waiting to see your next content 😊.

    2. 3

      Great post, very cool project.

      It’s crazy how ideas are just floating around.

      For the past few months I’ve been thinking about what I call “singe-server web apps” and “single-binary web apps”.

      What i’m interested in is simplifying the deployment of web apps on services like Linode or Digital Ocean by just uploading and running a single binary that contains everything needed including the DB and scheduled tasks. I was thinking about using Go with embedded HTML, CSS and images and SQLite as the DB. One could also use something like Litestream to make sure the DB is safe in the event of a major server failure, but that would require a “second server/binary”.

      I don’t really know what this is but the concept feels very appealing to me. Kinda reminds me of the PHP days where you just upload a script and just opened the browser. I know PHP still exists but it requires a web server and configuration to run. The idea of a single binary feels even more portable than PHP.

      Also https://redbean.dev/ is a very inspiring and interesting project.

      1. 2

        These exist. They are called unikernels and lots of people are using them.

        1. 1

          What is the advantage over CGI?

          1. 2

            CGI would assume that you are in a multi-process environment. Most unikernels are single-process (many are multi-threaded though). CGI would also assume all the usual unix trappings such as users, interpreters, shells, etc.

            The most obvious benefit is ease of use. There are no shells or interactivity with unikernels so when you deploy it - it’s either running or it’s not. While you can configure the server there isn’t ssh running where you pop in and do extra configure post-deploy.

            Then there is security. CGI quite literally is the canonical “shelling out” mechanism. CGI and the languages that heavily used it in the 90s and mid aughts were fraught with numerous security issues because of this practice. You have to deal with all the input/output sanitization and lots of edge cases.

            Then there is performance. CGI is woefully under performant since you have to spawn a new process for it and under more modern systems that use “big data” dealing with heaps in tens of gigabytes that becomes ridiculously bad.

            Anyways, very few people actually use ‘cgi’ as it were today. For languages that need to rely on a front-end proxy like nginx (because they are single process, single thread - like ruby, python, node, etc.) they siphon incoming requests off the front-end (nginx) and push it to your app back-end (your actual application).

            Unikernels work really well for languages that deal with threads like Go, Rust, Java, etc. They work well for scripting languages too but what I just described above the back-end becomes individual vms instead of worker processes. They basically force the end-user to fit their workloads to the appropriate instance type.

            1. 1

              The most obvious benefit is ease of use. There are no shells or interactivity with unikernels so when you deploy it - it’s either running or it’s not. While you can configure the server there isn’t ssh running where you pop in and do extra configure post-deploy.

              Isn’t that anti ease-of-use? I like to be able to go in and dig around when something goes wrong.

              1. 2

                IMO this makes debugging significantly easier than deploying to a linux system. If I throw on my devops hat and start thinking about all the times pagerduty woke me up at 2am in the morning half the time is spent figuring what process is causing an issue. Something is opening up too many sockets too fast? Open up lsof to figure what process it is. I can’t ssh in because logfiles are overflowing the disk? Now I have to hunt down the cronjob that I didn’t know existed that didn’t have proper log rotation on. In unikernel land there really is only one process so you know which program is causing the issue. Instrument it, ship your logs out and you are going to solve the vast majority of issues quickly.

                Also there are other cases where debugging is significantly easier. Since it’s a single process system you can literally clone the vm in production (say a live database), download the image and attach gdb to it and now you not only are going to find the root of the problem but you are going to do so in a way that is non-destructive and doesn’t touch prod.

                As an aside the ease-of-use I was referring too was not pertaining to debugging (although that is insanely easy) but to deployment/administration as compared to the dumpster fire of k8s/“cloud native”. Unikernels shift all the administration responsibilities to the cloud of choice. So while you can configure networking/storage to your hearts content you don’t have to actually manage it. Most people don’t understand this point about unikernels - they think a k8s like tool is necessary to use them which is totally not true - this won’t make sense to most people until they actually go deploy them for the first time and then this clicks.

                1. 1

                  I’d argue that’s a combination of A) familiarity, and B) linux OS having built out robust introspective/investigative tooling over decades.

                  A unikernel has the advantage that many of those investigative tools are for problems that no longer exist, and the disadvantage that it no longer has those tools baked-in for the problems that it does still have.

                  EG you don’t have du, but you also don’t have a local filesystem that can bring down the server when you accidentally fill it with logs/tempfiles.

                  1. 2

                    Most unikernels actually do work with filesystems as most applications that do anything want to talk to one. Databases, webservers, etc. Logging is dealt with mostly 2 ways: 1) You either don’t care and you just rely on what goes out the serial - which is stupid slow so not really a prod method or 2) You do care and you ship it out via syslog to something like elastic, papertrail, splunk, etc.

                    1. 1

                      EG you don’t have du, but you also don’t have a local filesystem that can bring down the server when you accidentally fill it with logs/tempfiles.

                      So how do you find out that your app e.g. crashes because some database key was NULL?

                      1. 2

                        You have logging and/or crash reporting and you do something useful with them. It’s your problem to do though, but that’s not really any different than deploying to a traditional stack.

                        1. 1

                          OK, but where do the logs go? If they go to another server, which then stores them on a filesystem you’ve just kicked the can elsewhere.

                          1. 1

                            Last I checked kicking the can down the road is most of IT :)

                            1. 1

                              Sure, but you can’t argue that e.g. you don’t have a filesystem to manage.

            2. 2

              If you wanted to use rust (or see about statically linking in a sqlite VFS via cgo) you could see about using https://GitHub.com/backtrace-labs/verneuil for sqlite replication. Completely in-process and exposes both a rust and C interface. It works quite well for all my home use cases, like for example replicating my blogs sqlite db to a s3 blob store for easier rollbacks.

            3. 2

              Very well done!

              We need more of this to be deployed for real life usage! Especially when done in C, Go, Rust, etc. Lots of resources to be saved by utilizing these faster languages compared to Ruby, Python or even PHP.