5

My first steps with Nix on Mac OSX as Homebrew replacement

 1 year ago
source link: https://sandstorm.de/de/blog/post/my-first-steps-with-nix-on-mac-osx-as-homebrew-replacement.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

My first steps with Nix on Mac OSX as Homebrew replacement

Sebastian Kurfürst20.06.2023

I finally had some time to play around with Nix - the immutable package manager and build system.  This was on my agenda since a long time, but I finally took the plunge on my M1 OSX system. I by no means understand Nix fully yet, but making progress and it is usable to me already.

Getting Started

I started by reading all of zero-to-nix.com - a great website which explains the first baby steps. For installing, I used the unofficial installer DeterminateSystems/nix-installer for reasons explained on the website, which ran through smoothly.

After doing the tutorials at zero-to-nix.com, I wondered how to continue. After all, I had two main goals:

  • have a reproducible global dev tool setup (basically a replacement for Homebrew)
  • have reproducible dev environments (basically replacing docker)

For the second use case, reproducible dev environments, I quickly settled on cachix/devenv. I also checked out jetpack-io/devbox which does fundamentally the same thing; but which hides the Nix files completely underneath - so that was too restrictive for my tastes.

When reading about the ecosystem, I saw there are lots of patterns how one could use Nix; and this is in flux right now, as the community irons out flakes (which many people seem to be using already though). So I for now decided on the following:

  • Embrace Nix Flakes: I'll only use nix flakes, especially after reading this blog post.
  • Only use the nix tool, instead of the older nix-env etc tools. It seems the new world and the old world sometimes are incompatible, and you need to decide which way to go consistently.
  • Only go declarative: I will never install a package by typing a CLI command, but always editing some configfile and running a "converge" script.

I have read that flakes and nix are still considered alpha; but from my perspective right now it feels 95% done - and maybe other projects would have called this a finished product by now. So I feel good about using this.

Global Dev Setup

For installing tools globally, I've read about nix profiles, but I was unsure about how to use them with Flakes. I then stumbled over this forum post, which is the way I am doing it now:

  1. I created a folder in ~/nix-sebastian (does not matter) containing my global Nix configuration.
  2. In this folder, I placed a flake.nix (content see below), effectively making this folder a flake.
  3. Then, for initial installation, I ran nix profile install . (inside the folder). This registered the flake.nix as part of the global nix profile. You can see that nix profile list shows the profile. 
  4. To update, you need to run nix profile upgrade 0 (assuming you only have this single profile installed) - if you have multiple profiles installed, you need to use the number displayed at the front of the listing.

Pitfall: you are not allowed to re-run nix profile install ., as this will install the profile a second time - and this will lead to conflicts. This is what I stumbled over at first :)

flake.nix skeleton

The following is the skeleton file I am using for global installation. To understand the syntax, this post about language basics and this post about functions have been helpful for me.

flake.nix
1 # flake.nix skeleton: 2 3 { 4 inputs = { 5 nixpkgs.url = "github:NixOS/nixpkgs"; 6 }; 7 8 outputs = { self, nixpkgs }: { 9 packages."aarch64-darwin".default = let 10 pkgs = nixpkgs.legacyPackages."aarch64-darwin"; 11 in pkgs.buildEnv { 12 name = "home-packages"; 13 paths = with pkgs; [ 14 15 # general tools 16 git 17 18 # ... add your tools here 19 ]; 20 }; 21 }; 22 23 }

Development Environments with devenv

I cannot say much about devenv.sh, except that it works as intended :) The docs are a bit sparse, but I found the devenv.nix file reference to be extremely helpful. It shows what you can all install and how you can customize the environment - I especially like the customizability of languages, and that the system supports services and scripts. As an example, for a Neos/Flow PHP application, I am using the following devenv.nix. It does not yet install all optimal PHP extensions, but it already sets up a database with permissions :)

In case you wonder, I used the "Advanced (declaratively with flakes)" installation method of devenv.sh described here.

devenv.nix
1 # devenv.nix 2 3 { pkgs, ... }: 4 5 { 6 languages.php.enable = true; 7 languages.php.package = pkgs.php82; 8 9 services.mysql = { 10 enable = true; 11 initialDatabases = [ 12 { name = "neos"; } 13 ]; 14 ensureUsers = [ 15 { 16 name = "neos"; 17 ensurePermissions = { 18 "neos.*" = "ALL PRIVILEGES"; 19 }; 20 } 21 ]; 22 }; 23 24 starship.enable = true; 25 }

Bonus and Closing Thoughts

So far I like what I saw :) I only played around with this for a few hours, but I was already able to remove most of my homebrew packages and convert them to Nix. I am curious where I will end up :)

In case you are interested, below is my current global flake.nix file, with the following specials:

  • install devenv
  • install diverse language toolchains (Rust, php, deno, node, JDK, go)
  • install PHP with extensions
  • custom-compile a PHP extension

my current global flake.nix file

flake.nix
1 # global flake.nix 2 { 3 inputs = { 4 nixpkgs.url = "github:NixOS/nixpkgs"; 5 unstable.url = "nixpkgs/nixos-unstable"; 6 devenv.url = "github:cachix/devenv/latest"; 7 8 # rust, see https://github.com/nix-community/fenix#usage 9 fenix = { 10 url = "github:nix-community/fenix"; 11 inputs.nixpkgs.follows = "unstable"; 12 }; 13 }; 14 15 outputs = { self, nixpkgs, unstable, devenv, fenix }: { 16 packages."aarch64-darwin".default = let 17 pkgs = nixpkgs.legacyPackages."aarch64-darwin"; 18 unstablePkgs = unstable.legacyPackages."aarch64-darwin"; 19 20 # see https://github.com/Mic92/nixos-wiki-test/blob/196aa6c3463bf52128d3ffb07218d0999b2ca617/PHP.md?plain=1#L38 21 php-vips = pkgs.php81.buildPecl { 22 pname = "vips"; 23 version = "1.0.13"; 24 sha256 = "TmVYQ+XugVDJJ8EIU9+g0qO5JLwkU+2PteWiqQ5ob48="; 25 buildInputs = [ pkgs.vips pkgs.pkg-config ]; 26 }; 27 php81 = pkgs.php81.buildEnv { 28 extensions = ({ enabled, all }: enabled ++ (with all; [ 29 xdebug 30 opcache 31 redis 32 php-vips 33 ])); 34 extraConfig = "memory_limit = 2G"; 35 }; 36 in pkgs.buildEnv { 37 name = "home-packages"; 38 paths = with pkgs; [ 39 40 # general tools 41 git 42 bitwarden-cli 43 ffmpeg 44 gnupg 45 curl 46 wget 47 jq 48 gnused 49 ripgrep 50 tmux 51 pandoc 52 53 # dev tools 54 devenv.packages.aarch64-darwin.devenv 55 mitmproxy 56 cfssl 57 dive 58 graphviz 59 lnav # log file nav 60 watchman 61 vector 62 kubectl 63 httpie 64 certstrap 65 lima 66 caddy 67 mutagen 68 mutagen-compose 69 upx 70 age 71 dbmate 72 gomplate 73 jwt-cli 74 ipcalc 75 ncdu 76 inetutils # telnet 77 78 # infrastructure 79 ansible 80 k3d 81 k9s 82 natscli 83 nats-server 84 redis 85 trivy 86 87 88 # programming environments 89 deno 90 nodejs 91 yarn 92 php81 93 symfony-cli 94 fenix.packages."aarch64-darwin".minimal.toolchain # rust 95 jdk17 96 97 # go 98 go 99 unstablePkgs.goreleaser 100 protobuf # TODO remove 101 protoc-gen-go # TODO remove 102 protoc-gen-go-grpc # TODO remove 103 golangci-lint # TODO remove 104 buf # TODO remove 105 gum # TODO REMOVE 106 107 108 #mariadb 109 #postgresql 110 111 112 # to remove 113 awscli 114 google-cloud-sdk 115 platformio 116 arduino-cli 117 openfortivpn 118 hcloud 119 120 pgcli 121 122 # mobile dev 123 # TODO Flutter does not work 124 cocoapods 125 fastlane 126 127 ]; 128 }; 129 }; 130 131 }

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK