gvalkov
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 :(
[1]: https://www.printables.com/model/866109-200mm-fan-front-for-...
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. 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.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
[1]: https://docs.python.org/3/whatsnew/3.11.html#whatsnew311-faster-cpython 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 cat id_rsa.pub | ssh $host 'dd of=.ssh/authorized_keys oflag=append conv=notrunc'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.
# /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/cnihttps://github.com/gvalkov/olympus-photosync-server https://github.com/gvalkov/olympus-photosync
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).
> Use it. Talk about it. Write about it.
I have a project that converts basic setup.py files to setup.cfg files [1].Still happily using plain setuptools for library development and pip-tools for application development.
from subprocess import run
run('foo | bar', shell=True, check=True)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/...
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. [0]: https://www.youtube.com/watch?v=ERS1OSOTGpgI 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-serverAs 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...
[1]: https://wtee.readthedocs.io/en/latest/
[2]: https://tailon.readthedocs.io/en/latest/https://pypi.io/ https://github.com/pypa/warehouse https://warehouse.readthedocs.io/