HN user

gvalkov

226 karma
Posts1
Comments72
View on HN

The squeeze is real even at the SME level. We recently wanted to add another TB of memory to several servers (we do EDA chip design, which eats a lot of memory). Quotes came back to about €200k for 48 x 96GB DDR5-5600 RDIMMs. Mind you, this is for refurbished memory with 1 year warranty. I'm still figuring out if this is FU-pricing or just how things are going to be from now on.

Spec-ing and buying servers has become quite the pain in the past year, at least at the relatively-small scale we operate at. It's "dynamic pricing" with most quotes being valid for 24 hours :(

In zsh you can bind "push-line-or-edit". In bash and all readline programs, you can approximate it with C-u followed by C-y (i.e. cut and paste). My history is still full of '#' and ':' (csh trauma) prefixed command-lines like you described though ...

This is nitpicking, but this is a good usecase for the := operator:

  if not (API_KEY := os.getenv("API_KEY")):
      ...
For internal tools I just let os.environ["API_KEY"] raise a KeyError. It's descriptive enough.

We're still serving a cgi-bin directory at work for the occasional quick and dirty internal web app. The ergonomics are great as long as you keep it simple. The fact that it's cgi doesn't mean you have to print http/1.0 to stdout manually. For example, in python the builtin wsgiref.handlers.CGIHandler lets you run any wsgi app as a cgi script:

  import wsgiref.handlers, flask
  app = flask.Flask(__name__)
  wsgiref.handlers.CGIHandler().run(app)
The way we run the scripts is with uwsgi and its cgi plugin[1]. I find it simpler and more flexible than running apache or lighttpd just for mod_cgi. Since uwsgi runs as a systemd unit, we also have all of systemd's hardening and sandboxing capabilities at our disposal. Something very convenient in uwsgi's cgi handling that's missing from mod_cgi, is the ability to set the interpreter for a given file type:
  cgi = /cgi-bin=/webapps/cgi-bin/src
  cgi-allowed-ext = .py
  cgi-helper = .py=/webapps/cgi-bin/venv/bin/python3  # all dependencies go here
Time to first byte is 250-350ms, which is acceptable for our use case.

[1] https://uwsgi-docs.readthedocs.io/en/latest/CGI.html

I recently built something[1] similar, though with far less effort and sophistication than the author. The goal was to have a plug-and-play audiobook player for an elderly family member with impaired vision. In retrospect, it would have been better to adapt an old phone or tablet with a macropad rather than build this on top of an espmuse speaker[2].

I keep thinking that a cassette player would be the ideal interface for something like this. The controls are as obvious and as tactile as it gets and the whole analog-mechanical experience is familiar to folks from that generation. If only tapes could hold more than two hours of audio ...

[1] https://www.printables.com/model/1269288-audiobook-player

[2] https://raspiaudio.com/product/esp-muse-luxe/

Python 3.11 also claims [1] to be 10-60% faster than 3.10, which is the version that the benchmarks game is using at this time. The difference in used RSS is also quite interesting in this comparison.

  [1]: https://docs.python.org/3/whatsnew/3.11.html#whatsnew311-faster-cpython

A hidden gem of pyenv is its 'python-build' plugin, which just lets you build and install any Python version in the least number of steps:

  git clone https://github.com/pyenv/pyenv.git
  cd pyenv/plugins/python-build/bin
  ./python-build --definitions
  ./python-build 3.10.8 /opt/python/3.10.8
  PYTHON_CONFIGURE_OPTS="--enable-shared" ./python-build 3.10.8 /opt/python/3.10.8

One nice use of dd is to append an ssh key to .authorized_keys on a host that doesn't allow shell or sftp access (which is what ssh-copy-id needs):

  cat id_rsa.pub | ssh $host 'dd of=.ssh/authorized_keys oflag=append conv=notrunc'

It's great to see how far Podman (and its sister projects) have come. I think it's a reliable tool and I'm a happy user both personally and professionally.

We make heavy use of Podman in our infrastructure and it's mostly a pleasure. My current pet peeves are that:

1) Ansible's podman_container module is not as polished as docker_container. I regularly run into idempotency issues with it (so lots of needlessly restarted containers).

2) Gitlab's Docker executor doesn't support Podman and all our CI agents run on CentOS 8. I ended up writing a custom executor for it and it's working quite well though (we're probably not going back to the container executor even if it supported Podman, since the custom executor offers so much more flexibility).

3) GPU support is easier/more documented on Docker. For this reason, the GPU servers we have are all Ubuntu 20.04 + Docker since it's the more beaten path.

4) Podman-compose just needs more work. Luckily for us, it seems that Podman 3.x will support docker-compose natively [1].

As mentioned, our CI environment is very dependent on Podman. The first step of every Gitlab pipelines is to build the container image in which the rest of the jobs will run. I find that it's simpler to have a shell executor in a unprivileged, restricted environment (i.e. can only run `podman build`) than setting up dind just for building images. All jobs that follow are ran in rootless containers, for that nice added layer of security.

Wishing all the best to the Podman, Buildah and Skopeo teams.

[1] https://www.redhat.com/sysadmin/podman-docker-compose

Quite a lot is possible with CNI [1]. For example, we use this setup to give real IPs to containers:

  # /etc/cni/net.d/testnet.conflist
  {
    "cniVersion": "0.4.0",
    "name": "testnet",
    "plugins": [
      {
        "type": "bridge",
        "bridge": "br0",  # main host interface is part of this bridge
        "ipam": {
          "type": "host-local",
          "subnet": "10.0.0.0/16",
          "gateway": "10.0.0.1",
          "routes": [{ "dst": "0.0.0.0/0"}]
        }
      }
    ]
  }
You can then start a container and operate on its network namespace for added flexibility:
  podman run -it --net testnet --ip 10.0.0.2 ...

  ns=$(basename $(podman inspect $id | jq -r '.[0] .NetworkSettings .SandboxKey'))
  ip netns exec $ns ip route add ...
[1]: https://github.com/containernetworking/cni

It's not possible in the way it's possible in SCons. You can basically use custom_target, but its usefulness is limited since there are no user-defined functions in Meson's subset of Python. CMake is a little better in this regard here, since it at least offers macros and functions.

Personally I see Meson as an attempt to do CMake right. A big differences between Meson and SCons is that SCons handles the execution of the build graph, while Meson delegates execution to Ninja. The nice thing about the former is that while the graph is being walked, new nodes can be added. The nice thing about the latter is that it's incredibly efficient.

I'm a build engineer and SCons is one of the gems in my tool belt. Where it truly shines is as a framework for building build systems. At its core, it's just a library for building and executing a DAG. What most SCons users work with is the standard-library of rules built on top of the core API, that makes it immediately usable as a "high-level" build system like Meson or Cmake. In my experience, it's unparalleled when you have to model an entirely custom build-flow in a clean way. I've used it to model build-flows for custom tool-chains that would have been a nightmare to reason about if they were written in GNU Make and outright impossible with a meta-build system.

The only other tools I've found to rival this flexibility are Gradle (see the Software Domain Modeling chapter of its documentation) and Shake (though having to write rules in Haskell makes it a hard pill to swallow).

12 Factor CLI Apps 8 years ago

A problem with color is that people end up optimizing the aesthetics for their own terminal setup. There is a wild number of different color schemes out there and it's really hard to make something that looks good on all of them. In my experience the only safe choice is bold text (i.e. \033[1m) since it stands out in all cases.

For a recent project (with modest needs), I just used a short makefile[1] and plain ES5. I found the experience refreshing as there is definitely peace of mind in depending on one less black box.

There is indeed something uncomfortable about a big node_modules directory or a magic build tool. It's almost like bathophobia, where instead of depths there is 3rd-party javascript code.

[1] https://github.com/gvalkov/tailon-next/blob/master/frontend/...

Fiy, heredocs also have a variant that strips all leading tab characters. Quoting from `man 1 bash`:

  If the redirection operator is <<-, then all leading   
  tab characters are stripped  from  input  lines  and  
  the line containing delimiter.  This allows here-
  documents within shell scripts to be indented in a  
  natural fashion.

Systemd is not orthogonal to lean and small-footprint systems. This is a good presentation on its use in embedded environments[0].

  [0]: https://www.youtube.com/watch?v=ERS1OSOTGpg

I've written many init scripts for SysV, upstart, OpenRC and FreeBSD's rc, but I've found that systemd's service units to be by far the cleanest and quickest way to muster up an init script (with FreeBSD's rc in second place).

I think it's great on the Raspberry Pi [0]. It boots quickly, has a low footprint and runs in diskless mode by default [1].

I most recently used Alpine and a RPi to make an appliance of sorts, that would wait for the SSID of my Olympus WiFi-enabled camera (it acts as an AP) to show up and then sync all new photos automatically [2].

  [0]: https://wiki.alpinelinux.org/wiki/Raspberry_Pi
  [1]: https://wiki.alpinelinux.org/wiki/Installation#Installation_Handbook
  [2]: https://github.com/gvalkov/olympus-photosync-server

The guile integration in gmake is a bit shallow, but still quite useful (here's the whole implementation [1][2]). It could also use more real-life usage examples - there's really nothing out there besides a few short snippets.

As a learning experience, I wanted to implement parts of the GMSL[3] on top of guile. It looked like it could be useful to others, so I made it into its own project: the GNU Make Toolkit[4] (it's still very much a work in progress - I've put more effort into the test suite and the documentation generator than into actual functionality).

[1] http://git.savannah.gnu.org/cgit/make.git/tree/guile.c

[2] http://git.savannah.gnu.org/cgit/make.git/tree/gmk-default.s...

[3] http://gmsl.sourceforge.net/

[4] https://github.com/gvalkov/gnu-make-toolkit