6,499 karma · joined November 17, 2015
It is unfortunate that the ADA is designed so that the only mechanism of enforcement of disability rights is lawsuits. :-\
Maybe there should be some exceptions around things provided on a "best-effort" basis, if they can be very carefully crafted.
Yeah, I think it makes sense to also let people point to arbitrary OCI registries. I'd bet support for that is coming, especially since the execution environment is Dockerized anyway.
> Pushing nix as the DX for GHA equivalent
I think something like Nix actually makes more sense than YAML for this kind of thing. You want a DSL that is purpose-built so that configurations are declarative, simple configurations are simple to write, and configurations are composable. YAML is too much of a straightjacket. Some kind of built-in support for deep merges is a must, imo.
How powerful/expressive the language should be is debatable, I think. I'm interested in Turing-complete DSLs like Nix and Nickel, but CUE could be a good fit here, too.
Anyway I'm sure they'll add first-class support for using some OCI artifact to define a CI environment. Looks like their CI implementation only recently entered the first alpha.
Scheduling jobs, actually getting them running, is virtually instant with GitLab but it's slow AF for GitHub for no discernable reason.
Angled quotes I use only on systems on which I've configured a compose key, or Android when I'm typing Chinese.
I don't like any kind of auto-replacement with physical keyboards, so I turn off "smart quotes" on macOS.
Anyway I use characters like that all the time, but it's never auto-replace.
Aside: it's probably just style (maybe some style guides call for the way you did it), but using em-dashes for this purpose with whitespace on each side of them looks/feels wrong to me. Anyone know if that's regional or something?
If Knoppix had this and Finnix didn't, or if Knopper was able to supply enhancements and bugfixes in order to support Knoppix releases, then he was likely able to fit a much more complete system onto a given CD or DVD.
But idk what kind of compression early Finnix used, if any. (Nowadays, everything uses SquashFS, right?)
> delete delete you must delete! set yourself free from attachment and loss you are not dead yet, so be alive and act!
> we are not here to make code: we are here to make changes
I want this on a T-shirt.
> YUP (Yellow Dog Updater) has been specially created for Yellow Dog Linux, and was adapted for other RPM based distributions with the name YUM (Yellowdog Updater, Modified).
Indeed, when I was in school, the WiFi networks were very poorly secured, so it was easy for annoying kids to get their own computers onto school networks if other students were using school-issued laptops around them. Annoying!
MaxStartups
Specifies the maximum number of concurrent unauthenticated
connections to the SSH daemon. Additional connections
will be dropped until authentication succeeds or the
LoginGraceTime expires for a connection. The default is
10:30:100.
Alternatively, random early drop can be enabled by
specifying the three colon separated values
start:rate:full (e.g. "10:30:60"). sshd(8) will refuse
connection attempts with a probability of rate/100 (30%)
if there are currently start (10) unauthenticated
connections. The probability increases linearly and all
connection attempts are refused if the number of
unauthenticated connections reaches full (60).
So it looks like it's possible to support ControlMaster while still somewhat hampering mass-cloning thousands of repos via SSH key without reauthenticating.Admittedly I'd put this more in the category of making endpoint compromise easier to detect than that of actually preventing any particular theft of data or manipulation of systems. But it might still be worth doing! If it means only a few dozen or only a hundred repos get compromised before detection instead of a few thousand, that's a good thing.
Besides all that (or MaxSessions, as another user mentions), if an attacker compromises a developer laptop and can only open those connections as long as the developer is online, that's one thing. But a plaintext key that they can grab and reuse from their own box is obviously an even sweeter prize!
"The SSH key on my YubiKey is useless to attackers" is obviously the wrong way to think about this, but using a smartcard for SSH keys is still a way to avoid storing plaintext secrets. It's good hygiene.
--
https://www.man7.org/linux/man-pages/man5/sshd_config.5.html
I admit that when I went to the CUE documentation (because I was learning Dagger!) and read about the idea of thinking of validation as locating both schema and configuration on an infinite type/value lattice and sort of walking down from schema to concrete configuration, I thought "holy shit, it makes perfect sense". I'd never really thought about unification in configuration languages before, and it's a really cool idea, one of those things that's simple enough to be intuitive but also really powerful. First-class deep merge support is something that I really miss in hacky configuration languages like HCL, for example. So right away I felt "these CUE guys are onto something! let's see how it pans out".
It felt painful for me to abandon that investment, as I'm sure it did for many on your team, too.
While I'm fairly happy with what I've managed to do since moving on from using Dagger, the CI space is still a mess overall, and I think it needs tools like Dagger and more. So while it will likely be some time before I reevaluate Dagger for use at my current job, I do still wish you and your team present and continued success!
Thanks again for dropping by and listening.
Instead I used the scripts module to write shell scripts that bring along all of their dependencies. Thus all of our GitLab jobs are just one-line invocations of our wrapper scripts. We currently use a flake.nix-based Devenv and expose the scripts from the Devenv module as flake outputs, then just run them with `nix run`.
Nowadays, though, Devenv actually directly supports some relevant functionality in the form of tasks¹, which can be written in any language, and support dependency relationships and run concurrently by default.
We use those in a few places as well, though mostly in place of older, cruder `enterShell` integration. There, we use them: - to seamlessly ensure correct state of Git extensions: - all Git submodules are checked out - Git-LFS is configured and all large files are correctly checked out - to ensure valid OpenTofu caches since we use Nix instead of OpenTofu for managing providers - if .terraform dir doesn't exist, run `tofu init` - if Terraform providers lock file is older than devenv lock, run `tofu init -upgrade` - manage Poetry stubs and virtualenvs (most of this is configured behind the scenes upstream, but we do some extra stuff) - manage Bundler dependencies and binstubs for Ruby projects so executables under development can be involed naively from PATH (much of this is bespoke but upstreamable)
So a lot of those Devenv tasks are things you might do in build or pre-build stages of a CI pipeline. You can define the requisite dependency relationships and then just run `devenv test` or `devenv tasks ...` as your CI job.
What we don't have is any abstraction over the various CI platforms we use (currently GitLab, GitHub, and AzDO, with Jenkins support in the backlog). Unfortunately, for the sake of a better DX for our (internal) customers, we still integrate fairly directly with each CI platform, so we do have piles of vendor-specific YAML.
Our tasks and scripts are currently just Bash, but they're relatively nice Bash because their dependencies are managed with resholve and they're linted by ShellCheck, thanks to some experimental changes I made to Devenv's scripts module.
For our security/quality scans, we do, however, have some logic nestled in those Bash scripts which checks for a CI environment via env vars, then performs differential rather than full scans if we're in merge request contexts. Where the upstream tools don't directly support this, we basically perform "before" and "after" scans and take a diff. This is the direction I'd like to go in the future— all in on this, surfacing jobs in a "native" way be damned.
Unfortunately I can't directly share these examples as they belong to my employer and live in proprietary projects. But what I can do is open a couple of WIP PRs for the upstreamable work (new or modified Devenv modules) so you can take a look at that at least.
Also fwiw I think Dagger is still worth checking out. I just feel a bit burned by adopting it too early in its lifecycle, and generally advice caution about adopting tools developed by VC-backed startups.
--
I think multi-language support is a great feature, and I understand why you had to go for it. While I'm sure some people likely switched away from CUE once they had the chance because they weren't interested in working with a novel and perhaps quirky DSL, I'm also sure some stopped using the CUE SDK just because it was clear to them that it was being abandoned— I know that because I'm one of them. I'm one of the users who stopped using the CUE SDK after multi-language support came out— and it's not because I preferred using one of those other languages. That's all I'm saying.
That is, of course, a self-fulfilling prophecy (or, perhaps, a self-inflicted wound). As soon as Dagger's "multi-language support" came out (actually a bit before), the CUE SDK was rendered abandonware. Development only happened on the new backend, and CUE support was never ported over to the new one.
We used Dagger, and later Nix, mostly to implement various kinds of security scans on our codebases using a mix of open-source tools and clients for proprietary ones that my employer purchases. We've been using Nix for years now, and still haven't set up any of our own binary cache. But we still have mostly-cached builds thanks to the public NixOS binary cache, and we hit that relatively sparingly because we run those jobs on bare metal in self-hosted CI runners. Each scan job typically finishes in less than 15 seconds once the cache is warm, and takes up to 3 minutes when the local cache is cold (in case we build a custom dependency).
Some time in the next quarter or two I'll finish our containerization effort for this so that all the jobs on a runner will share a /nix/store and Nix daemon socket bind-mounted from the host, so we can have relatively safe "multi-tenant" runners where all jobs run under different users in rootless Podman containers while still sharing a global cache for all Nix-provided dependencies. Then we get a bit more isolation and free cleanup for all our jobs but we can still keep our pipelines running fast.
We only have a few thousand codebases, so a few big CI boxes should be fine, but if we ever want to autoscale down, it should be possible to convert such EC2 boxes into Kubernetes nodes, which would be a fun learning project for me. Maybe we could get wider sharing that way and stand up fewer runner VMs.
Somewhere on my backlog is experimenting with Cachix, so we should get per-derivation caching as well, which is finer-grained than Docker's layers.
Then they completely abandoned not just the CUE frontend, but CUE altogether (while strenuously denying that they were doing so) for a GraphQL-based rewrite that focused on letting people use popular general-purpose languages to construct their workflows. The initial rollout of this was not feature complete and only supported imperative languages (Python and TypeScript, IIRC), which I didn't like.
Instead of porting everything over to all their new interfaces, I hopped off the train and rewrote all of our portable pipeline scripts in Nix, via Devenv. At the time, I'd never used Devenv before, but getting the work done that time still took maybe a tenth of the time or less. More than anything else, this was due to not having to fuck around with the additional overhead Docker entails (fussing with mount points, passing files from one stage to another, rebuilding images, setting up VMs... all of it). I got the reproducibility without the extra bullshit, and got to work with interfaces that have proven much more stable.
I still think there's a place for something like Dagger, focused just on CI, perhaps even still using Docker as a deployment/distribution strategy. But I no longer trust Dagger to execute on that. I think a proper external DSL (probably special-purposw but still Turing-complete, e.g., Nickel) is the right fit for this domain, and that it should support multiple means of achieving repeatability rather than just Docker (e.g., Nix on bare metal and Podman, to start). An option to work on bare metal via reproducible environment management tools like Nix, Guix, or Spack is a valuable alternative to burdensome approaches like containers.
I haven't looked at Dagger in several months, but the other big piece that is missing for portable CI workflows is a library that abstracts over popular CI platforms so you can easily configure pull/merge request pipelines without worrying about the implementation details like what environment variables each platform exposes to indicate source and target branch.
Idk anything about all the AI horseshit; I was off the Dagger bandwagon before they took that turn. I don't know if it's serious or a nominal play to court investors. But that kind of pivot is another reason not to build core infra on top of the work of startups imo. If the product is 70% of what you want, you have no way of knowing whether filling that 30% gap is something the maintainers will suddenly pivot away from, even if their current direction looks aligned with yours.
I'd recommend considering tools in this space only if (a) they're already close to 100% of what you need and (b) they're open-source. Maybe you can relax (a) if it's really easy to extend the codebase (I find this to be true for Devenv's Nix modules, for example.)
The last 3-4 releases have really enriched vanilla Emacs (LSP support, tree sitter support, project.el). Emacs adds default packages somewhat conservatively but it seems like everything that gets included by default ends up with very solid integration/support with other packages
> As a sysadmin that has to often jump from machine to machine it’s nice to be able to install whatever emacs release the os vendor ships and be productive
Quite true, although TRAMP gives Emacs users another good alternative to "bringing the config along"!
> As a sysadmin
I think it's also fair for operators to install the tools they use/like the most on the systems they administer. If a more recent Emacs release makes you happier, why not use Guix to include a portable copy of the latest release on all your servers?
His ugly sh example:
morning_greetings=('hi' 'hello' 'good morning')
energetic_morning_greetings=()
for s in "${morning_greetings[@]}"; do
energetic_morning_greetings+=( "${s^^}!" )
done
and his more readable Python equivalent: morning_greetings = ['hi', 'hello', 'good morning']
energetic_morning_greetings = \
[s.upper() + '!' for s in morning_greetings]
And I'd write the shell version in Bash something like this: morning_greetings=(hi hello 'good morning')
printf '%s!\n' "${morning_greetings[@]}" \
| tr '[:lower:]' '[:upper:]' \
| readarray -t energetic_morning_greetings
Does it still involve more syntax? Yeah. Printing arrays in Bash always involves some. But it's clearer at a glance what it does, and it doesn't involve mutating variables.The piece this example is too simple to show (since it's focused only on data operations and not interacting with the filesystem or running external programs) is how much shorter the Bash usually ends up being than the Python equivalent.