diff options
Diffstat (limited to 'articles')
-rw-r--r-- | articles/2024-05-03-replaced-infra.md | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/articles/2024-05-03-replaced-infra.md b/articles/2024-05-03-replaced-infra.md new file mode 100644 index 0000000..1177d7b --- /dev/null +++ b/articles/2024-05-03-replaced-infra.md @@ -0,0 +1,107 @@ +# infra - my homebrew package and configuration manager + +The last 8 months I was configuring my server with my own little package manager +[`infra`](https://codeberg.org/metamuffin/infra) before just recently replacing +it again a few days ago for reasons I will mention later. This had multiple +reasons; primarily that I want to version control all configuration of all my +servers (the VPS and a Raspi) from one source-controlled repository. + +## infra good + +My "package manager" was actually more like a library where one would write code +to specify how the machines were set up. This is similar to how Nix or Guix do +it. My implementation however was written in Rust and initially hacked together +in a few hours. Let's look at an example: + +```rs +// You would pass credentials to the machine here +let m = Machine::new(...); + +// Load a minimal gnix config without any hosts. +let mut gnix = Gnix::load(include_str!("gnix_base.yaml")) + +m.install(Fastbangs { + // Here gnix automatically allocates a new port for internal proxying. + bind_addr: gnix.new_host("search.metamuffin.org"), + data_dir: "/var/local/fastbangs".into(), + ..Default::default() +}.service()); + +m.eu1.install(MetamuffinWebsite { + bind_addr: eu1_gnix.new_host("metamuffin.org"), +}.service()); // `service` transforms the mere software configuration to a systemd service that uses it. + +m.install(gnix); +``` + +Infra would for this example automatically download, compile, install, configure +and start/enable required services. It was a total solution. The current state +of each machine (i.e. installed packages) was tracked locally. Whenever the +deployment specification changes, a diff is calculated and applied +incrementally. Applying an installation is very general term in infra, it could +mean placing some configs somewhere but also starting and stopping systemd +services or whatever. + +Procedurally generating the server configuration had more advantages than not +struggling with port numbers, I could also create fully meshed Wireguard VPNs +with ease. Something that is considerably more pain if done manually. The +following excerpt creates such a network, automatically assigns IP addresses and +even writes hostnames to `/etc/hosts`. + +```rs +let mut hosts = HostsFile::default(); +let mut wg_myservers_subnet = IpSubnet([10, 123, 0, 0].into(), 16); +let wg_myservers = WireguardMesh::new("myservers", 16); +server1.install(wg_myservers.add_peer( + hosts.register(wg_myservers_subnet.next(), "server1"), + "server1.example.org:12345".into(), + "SECRET VALUE GOES HERE" +)); +server2.install(wg_myservers.add_peer( + hosts.register(wg_myservers_subnet.next(), "server2"), + "server2.example.org:12345".into(), + "SECRET VALUE GOES HERE" +)); +server3.install(wg_myservers.add_peer( + hosts.register(wg_myservers_subnet.next(), "server2"), + "server3.example.org:12345".into(), + "SECRET VALUE GOES HERE" +)) +for s in [server1, server2, server3] { + s.install(hosts); +} +``` + +## infra bad + +Like mentioned the state was tracked locally, which meant I was restricted to a +single machine for maintaining my server. + +Also, and this is the worst part, infra would manage the server by connecting +via SSH and executing random commands through a simple shell wrapper. This +process will not take any feedback about the success about what it did. +Obviously all commands are executed intelligently but if the connection broke or +something else destabilized the system, there was no way to fix it trivially. + +Another problem was transparency. Although infra allows exporting an overview of +your deployment as a directed graph, it still didn't suffice for a good +understanding about what was configured where. Sometimes I would install two +packages that wrote to the same configuration - something that infra does not +worry about - and get unexpected results. + +It could also be considered a minor problem, that some configuration files just +don't prettier when written with a Rust DSL. + +## infra useless? + +`infra` is flawed. It just doesn't work if you have anything serious to +maintain. However the basic concept of generating configuration from code is +quite nice and were somewhat elegant to use sometimes. + +In the last week I replaced infra in my deployments with a different system that +I will describe in the next article. Going forward though I am thinking of +taking the best from infra and turning it into a static configuration and script +generator to be used in the new system. + +That's that. If you have any interesting feedback or thoughts on this topic, +please [reach out](/contact). |