UML diagram for the DDD example in Evans' book (github.com)
How a yacht works: sailboat physics and design (onemetre.net)
College Towns: Urbanism from a Past Era (governance.fyi)
Show HN: Attune - Build and publish APT repositories in seconds
Previously, we worked at other startups building open source developer tools that ran on our customers’ CI and development machines. For many of them, being able to `apt-get install` our tools was a requirement.
When we went to actually set up APT repositories, we were really surprised by the state of tooling around package publishing. The open source tools we found were old, slow, and difficult to figure out how to run in CI. The commercial tools we found were not much better. The cloud-hosted vendors required us to provide our signing keys to a cloud vendor (which was a non-starter), while the self-hosted vendors required us to operate our own specialized hosting servers.
We just wanted something simple: sign locally, run quickly, be easy to use, and deploy to managed object storage.
We couldn’t find it, so we built it. If you want to try it out, you can create a repository with three commands:
attune repo create --uri https://apt.releases.example.com
attune repo pkg add --repo-id 123 package.deb
attune repo sync --repo-id 123
You can get the tool at https://github.com/attunehq/attune. There are a lot of rough edges right now since it's so new - sorry in advance, we're working on sanding those down.It’s fully open source under Apache 2. We’re also working with some early customers to build enterprise features like audit logging, RBAC, and HSM integrations, and we’re thinking about building a managed cloud hosting service as well.
We’d love your feedback on whether this is useful for you, and what you’d like to see next. We’re well aware that publishing is a small piece of CI/CD, but we think a lot of the tooling in this area (publishing, artifact registries, package repositories) could really use some love.
What do you think? Comment here, or email us at founders@attunehq.com.
Also, from your post here (and why are the quick start steps different here?),
What is that URI supposed to be? Is that where the thing will eventually get served from and I have to run this on the server, or synchronize an output directory to the server, or is that going to do some sort of magic upload itself?To answer your direct question: on self-hosted repositories, the URI right now is just a string identifier. We are working right now on a cloud hosted service, and there the URI will help us figure out which repository to actually serve.
What would be really valuable for us would be future support for other distros/repos.
A more unified interface for synchronized publishing across say dep/rpm/archlinux/alpine when we have multi-distro packages to build and publish.
1. Aptly needs to rebuild the entire repository before it can do any changes. One of our customers builds packages for every Linux OS, and every architecture, and each release contains 10-something separately packaged tools, and they do regular releases. This means their repository of packages is _huge_. When they try to do small maintenance actions like removing a package that has a bug, they need to rebuild their entire repository to do this, which takes upwards of 30 minutes. On Attune, since we have a centralized control plane, it takes about 10 seconds.
2. Aptly doesn't have concurrency controls. This makes it annoying to run in CI. Imagine you're setting up a CI pipeline that runs on every commit and publishes a package. You need to make sure you don't have two different instances of Aptly running at the same time, because their updates will clobber each other if they publish at the same time. Can you ensure that your CI only ever runs one publish at a time? This is easy in some setups, but surprisingly hard in GitHub Actions - concurrency keys don't quite work the way you'd expect them to.
3. Aptly uses its storage as its source of truth for the current state of packages. This is a great design choice for simplicity! However, if your CI job dies halfway through during an Aptly publish, this can leave your repository in a corrupted (in this case, half-updated) state. To recover from this, you need to rebuild the repository state... which you can't, because the ground truth is contained in the storage which was just corrupted! We mitigate this issue by tracking metadata in a separate transactional database so CI crashes don't cause corruption.
These are some examples of little cuts that build up over time with all of the tools we've found so far. Lots of the open source tooling is great at low scale, but the cuts start to build up once you are pushing a meaningful amount of packages to production.
Most of these scripts were designed for a world where there was A Blessed Deployment Machine that acted as its own de facto centralized control plane. We're designed for a newer world where publishing is just another piece of your CI, so you need more features to handle concurrency control, distributed signing, incremental index rebuilds, etc.
To our knowledge, we have not found another provider who supports both of these requirements. It's not some amazing technical innovation, but it is one of those annoying paper cuts that builds up with all the others.
Debian and Ubuntu have been using them in production and "at scale" for decades. What are the "sharp edges" that you're trying to solve?
I have a few pain points with that for installing cua (https://github.com/trycua/cua/issues/27), so if it can remove the initial friction happy to chat!
Excited to try. I ran a reprepo for a couple of years & it wasn't the worst to run, but not fun either. My confidence in efficiently publishing packages was super low, never improved much.
It also mandated running a web server (configuring my nginx to point at the repo filesystem), not very batteries included.
https://wiki.debian.org/DebianRepository/SetupWithReprepro
We're also working on a hosted service! If you'd like a sneak peek, send us a message at founders@attunehq.com (or email me directly at eliza@attunehq.com). I'm happy to talk about your specific needs and see if we can build something for them.
(And yes, it is Rust. I keep trying to find projects where I get to stretch my Haskell wings again, but unfortunately I keep working on things with silly requirements such as "easily understandable performance" and "a cross-compilation story" and "not making my collaborators sit through another monad tutorial".)