Compare commits

...

10 commits

16 changed files with 536 additions and 187 deletions

126
darwin/common.nix Normal file
View file

@ -0,0 +1,126 @@
{
pkgs,
lib,
nix-darwin,
...
}:
{
environment.systemPackages = with pkgs; [
home-manager
jetbrains.clion
jetbrains.idea-ultimate
jetbrains.pycharm-professional
jetbrains.webstorm
];
environment.darwinConfig = "/Users/irl/.config/nix-configs";
nix = {
package = pkgs.nix;
settings = {
"extra-experimental-features" = [
"nix-command"
"flakes"
];
};
};
nixpkgs.config.allowUnfreePredicate =
pkg:
builtins.elem (lib.getName pkg) [
"clion"
"idea-ultimate"
"pycharm-professional"
"webstorm"
];
homebrew = {
enable = true;
onActivation = {
autoUpdate = true;
cleanup = "zap";
};
brews = [
"libfido2"
"mas"
"openssh"
"theseal/ssh-askpass/ssh-askpass"
];
casks = [
"affinity-designer"
"affinity-photo"
"affinity-publisher"
"audacity"
"discord"
"element"
"fantastical"
"firefox"
"ghostty"
"notion"
"obsidian"
"tor-browser"
"vlc"
];
masApps = {
"Things" = 904280696;
};
taps = [
"theseal/ssh-askpass"
];
};
programs = {
# TODO: rewrite in fish maybe
zsh.shellInit = ''
export SSH_ASKPASS=/opt/homebrew/bin/ssh-askpass
export SSH_ASKPASS_REQUIRE=force
checkSSHAgent() {
if [ "$1" = "-k" ] ; then
pkill -9 ssh-agent
fi
ssh_agent_conf="$HOME/.ssh/agent"
if [ -e "$ssh_agent_conf" ] ; then
. "$ssh_agent_conf"
fi
if ! ps aux | awk '{print $2}' | grep -q "$SSH_AGENT_PID" \
|| ! [ -e "$ssh_agent_conf" ] \
|| [ -z "$SSH_AGENT_PID" ] ; \
then
ssh-agent -s | grep -v echo > "$ssh_agent_conf"
. "$ssh_agent_conf"
fi
}
checkSSHAgent
'';
};
system = {
defaults.NSGlobalDomain = {
"com.apple.swipescrolldirection" = false;
};
primaryUser = "irl";
stateVersion = 6;
};
users.users = {
irl = {
description = "irl";
home = "/Users/irl";
name = "irl";
# This is the macOS zsh, not from nix!
# My home-manager configuration contains some zshrc to automatically
# start fish for interactive shells where the parent process is not
# already fish.
shell = "/bin/zsh";
};
};
}

7
darwin/irl-mac-mini.nix Normal file
View file

@ -0,0 +1,7 @@
{
lib,
...
}:
{
networking.hostName = "irl-mac-mini";
}

46
flake.lock generated
View file

@ -82,11 +82,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749131129, "lastModified": 1751569544,
"narHash": "sha256-tJ+93i7N4QttM75bE8T09LlSU3Mv6Dfi9WaVBvlWilo=", "narHash": "sha256-iWjzNHaSU+pm4TS/vzkzgBdbTwkyHy8Jc6PlcrgdgyU=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "13a45ede6c17b5e923dfc18a40a3f646436f4809", "rev": "28639e6470ef597fe9f5efc4c6594306859d62ed",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -95,13 +95,34 @@
"type": "github" "type": "github"
} }
}, },
"nix-darwin": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1751313918,
"narHash": "sha256-HsJM3XLa43WpG+665aGEh8iS8AfEwOIQWk3Mke3e7nk=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "e04a388232d9a6ba56967ce5b53a8a6f713cdfcf",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1749145035, "lastModified": 1751571573,
"narHash": "sha256-7hU9TqHpz3BhcgoP3J/udnvZ3QCurGEBD+ERhvKbJEE=", "narHash": "sha256-vyhLXk2EsyTSxZ8cETmAAUF/fp8hQ3lZ6fUC0p6+LsY=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "a537c74d1071ca48aa835f731998094a4058a6f3", "rev": "e50e2a177e0aaa0fd02c10fa365252f91b50cbf4",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -135,11 +156,11 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1749201010, "lastModified": 1751571902,
"narHash": "sha256-haiPLogZwEFQTrIarZD92LUK7ScIcMbtEzPlcC988Qk=", "narHash": "sha256-5EimK/KBs+UHVC3d9L1oagFWIzOlU2lOq0eI5kOTTWI=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NUR", "repo": "NUR",
"rev": "17efc5275a8f21e2b48f39ecade74cdaff3ba411", "rev": "b19bd45d58ab88e1700cc3032139676fae7f3ea1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -153,6 +174,7 @@
"apple-silicon": "apple-silicon", "apple-silicon": "apple-silicon",
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"home-manager": "home-manager", "home-manager": "home-manager",
"nix-darwin": "nix-darwin",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nur": "nur", "nur": "nur",
"sops-nix": "sops-nix" "sops-nix": "sops-nix"
@ -163,11 +185,11 @@
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1749592509, "lastModified": 1750119275,
"narHash": "sha256-VunQzfZFA+Y6x3wYi2UE4DEQ8qKoAZZCnZPUlSoqC+A=", "narHash": "sha256-Rr7Pooz9zQbhdVxux16h7URa6mA80Pb/G07T4lHvh0M=",
"owner": "mic92", "owner": "mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "50754dfaa0e24e313c626900d44ef431f3210138", "rev": "77c423a03b9b2b79709ea2cb63336312e78b72e2",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -1,6 +1,5 @@
{ {
description = "I have no idea what I'm doing"; description = "I have no idea what I'm doing";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs"; nixpkgs.url = "github:nixos/nixpkgs";
apple-silicon = { apple-silicon = {
@ -12,6 +11,10 @@
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nix-darwin = {
url = "github:nix-darwin/nix-darwin/master";
inputs.nixpkgs.follows = "nixpkgs";
};
nur = { nur = {
url = "github:nix-community/NUR"; url = "github:nix-community/NUR";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@ -23,25 +26,31 @@
}; };
outputs = outputs =
{ {
nixpkgs,
apple-silicon, apple-silicon,
flake-utils, flake-utils,
home-manager, home-manager,
nix-darwin,
nixpkgs,
nur, nur,
self,
sops-nix, sops-nix,
...
}@inputs: }@inputs:
let let
homeRoles = [
"desktop"
"minimal"
"server"
];
outputs = inputs.self;
overlays = [
apple-silicon.overlays.apple-silicon-overlay
nur.overlays.default
];
supportedSystems = [ supportedSystems = [
"x86_64-linux" "x86_64-linux"
"aarch64-darwin" "aarch64-darwin"
"aarch64-linux" "aarch64-linux"
]; ];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
overlays = [
apple-silicon.overlays.apple-silicon-overlay
nur.overlays.default
];
in in
{ {
nixosConfigurations = { nixosConfigurations = {
@ -64,31 +73,35 @@
specialArgs = inputs; specialArgs = inputs;
}; };
}; };
homeConfigurations = nixpkgs.lib.foldl' ( homeManagerModules = import ./modules/home-manager;
acc: system: homeConfigurations = nixpkgs.lib.foldl' (c: e:
acc c // {
// { "irl-${e.role}-${e.system}" = home-manager.lib.homeManagerConfiguration {
"irl-${system}" = home-manager.lib.homeManagerConfiguration {
pkgs = import nixpkgs { pkgs = import nixpkgs {
inherit system overlays; inherit overlays;
system = e.system;
}; };
modules = [ ./home/irl.nix ]; extraSpecialArgs = {
}; inherit outputs;
"irl-gui-${system}" = home-manager.lib.homeManagerConfiguration {
pkgs = import nixpkgs {
inherit system overlays;
}; };
modules = [ modules = [
./home/irl.nix ./home-manager/irl.nix
{ { role = "${e.role}"; }
irl.gui-packages = true;
}
]; ];
}; };
} }
) { } supportedSystems; ) { } (nixpkgs.lib.cartesianProduct { role = homeRoles; system = supportedSystems; });
} }
// flake-utils.lib.eachSystem supportedSystems (system: { // flake-utils.lib.eachSystem supportedSystems (system: {
formatter = nixpkgs.legacyPackages.${system}.nixfmt-rfc-style; formatter = nixpkgs.legacyPackages.${system}.nixfmt-tree;
}); })
// {
darwinConfigurations."irl-mac-mini" = nix-darwin.lib.darwinSystem {
system = "aarch64-darwin";
modules = [
./darwin/common.nix
./darwin/irl-mac-mini.nix
];
};
};
} }

40
home-manager/irl.nix Normal file
View file

@ -0,0 +1,40 @@
{
config,
lib,
outputs,
pkgs,
...
}:
{
imports = builtins.attrValues outputs.homeManagerModules;
options.role = lib.mkOption {
description = "Home role to set up";
default = "minimal";
type = with lib.types; enum ["desktop" "minimal" "server"];
};
config = {
feature.cli.enable = builtins.elem config.role ["desktop" "minimal" "server"];
feature.firefox.enable = config.role == "desktop";
feature.git.enable = builtins.elem config.role ["desktop" "server"];
feature.ops.enable = config.role == "desktop";
feature.tmux.enable = builtins.elem config.role ["desktop" "server"];
feature.vim.enable = builtins.elem config.role ["desktop" "minimal" "server"];
home.username = "irl";
home.homeDirectory =
if lib.strings.hasSuffix "darwin" pkgs.system then "/Users/irl" else "/home/irl";
home.packages = with pkgs; [
neofetch
];
home.shellAliases = {
hms =
"home-manager switch --flake ~/.config/nix-configs#irl-${config.role}-${pkgs.system}";
drs = "sudo darwin-rebuild switch --flake ~/.config/nix-configs";
};
home.stateVersion = "25.05";
programs.home-manager.enable = true;
};
}

View file

@ -1,149 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.irl;
in
{
options.irl.gui-packages = lib.mkEnableOption "GUI packages managed by home-manager";
config = {
home.username = "irl";
home.homeDirectory =
if lib.strings.hasSuffix "darwin" pkgs.system then "/Users/irl" else "/home/irl";
home.stateVersion = "25.05";
home.packages = with pkgs; [
age
fish
neofetch
rust-analyzer
starship
tree
];
home.shellAliases = {
hms =
"home-manager switch --flake ~/.config/nix-configs#irl"
+ (if cfg.gui-packages then "-gui" else "")
+ "-${pkgs.system}";
};
programs.bash = {
enable = true;
initExtra = ''
if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
then
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
fi
'';
};
programs.firefox = lib.mkIf cfg.gui-packages {
enable = true;
profiles.irl = {
extensions = {
force = true;
packages = with pkgs.nur.repos.rycee.firefox-addons; [
bitwarden
kagi-search
privacy-badger
];
};
settings = {
"extensions.autoDisableScope" = 0;
};
};
};
programs.fish.enable = true;
programs.fzf = {
enable = true;
enableFishIntegration = true;
};
programs.git = {
delta.enable = true;
enable = true;
extraConfig = {
diff = {
algorithm = "histogram";
};
init = {
defaultBranch = "main";
};
rebase = {
autosquash = true;
autostash = true;
};
url = {
"git@github.com:".pushInsteadOf = "https://github.com/";
"git@gitlab.com:".pushInsteadOf = "https://gitlab.com/";
"git@guardianproject.dev:".pushInsteadOf = "https://guardianproject.dev/";
};
user = {
name = "irl";
email = "iain@learmonth.me";
};
};
};
programs.home-manager.enable = true;
programs.neovim = {
defaultEditor = true;
enable = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
plugins = with pkgs.vimPlugins; [
bufferline-nvim
nvim-lspconfig
nvim-treesitter.withAllGrammars
];
extraLuaConfig = ''
vim.lsp.config('rust_analyzer', {
settings = {
['rust-analyzer'] = {},
},
})
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('my.lsp', {}),
callback = function(args)
local client = assert(vim.lsp.get_client_by_id(args.data.client_id))
if client:supports_method('textDocument/implementation') then
-- Create a keymap for vim.lsp.buf.implementation ...
end
-- Enable auto-completion. Note: Use CTRL-Y to select an item. |complete_CTRL-Y|
if client:supports_method('textDocument/completion') then
-- Optional: trigger autocompletion on EVERY keypress. May be slow!
-- local chars = {}; for i = 32, 126 do table.insert(chars, string.char(i)) end
-- client.server_capabilities.completionProvider.triggerCharacters = chars
vim.lsp.completion.enable(true, client.id, args.buf, {autotrigger = true})
end
-- Auto-format ("lint") on save.
-- Usually not needed if server supports "textDocument/willSaveWaitUntil".
if not client:supports_method('textDocument/willSaveWaitUntil')
and client:supports_method('textDocument/formatting') then
vim.api.nvim_create_autocmd('BufWritePre', {
group = vim.api.nvim_create_augroup('my.lsp', {clear=false}),
buffer = args.buf,
callback = function()
vim.lsp.buf.format({ bufnr = args.buf, id = client.id, timeout_ms = 1000 })
end,
})
end
end,
})
'';
};
programs.starship = {
enable = true;
enableFishIntegration = true;
enableInteractive = true;
enableTransience = true;
};
programs.zellij.enable = true;
services.ssh-agent.enable = true;
};
}

View file

@ -0,0 +1,70 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.feature.cli;
in
{
options.feature.cli = {
enable = lib.mkEnableOption "Set up the CLI";
};
config = lib.mkIf cfg.enable {
home.packages = with pkgs; [
starship
tree
];
programs.fish = {
enable = true;
functions.fish_greeting = "";
shellInitLast = lib.mkIf (lib.strings.hasSuffix "darwin" pkgs.system) ''
eval $(/opt/homebrew/bin/brew shellenv)
'';
};
programs.fzf = {
enable = true;
enableFishIntegration = true;
};
programs.zsh = lib.mkIf (lib.strings.hasSuffix "darwin" pkgs.system) {
enable = true;
# zsh is a POSIX compliant shell and a safe default, but if it's an interactive
# shell and fish is not in the parent processes (i.e. I'm not deliberately starting
# zsh to use interactively from fish) then just launch fish.
initContent = ''
[[ $- == *i* ]] || return
is_parent_fish() {
local ppid=$$
while [[ $ppid -ne 1 ]]; do
local ppname=$(ps -p $ppid -o comm=)
if [[ "$ppname" == *fish* ]]; then
return 1
fi
ppid=$(ps -o ppid= -p $ppid)
done
return 0
}
if is_parent_fish
then
exec fish -l
fi
'';
};
programs.starship = {
enable = true;
enableFishIntegration = true;
enableInteractive = true;
enableTransience = true;
settings = builtins.fromTOML (builtins.readFile ./starship.toml);
};
};
}

View file

@ -0,0 +1,9 @@
[shell]
disabled = false
format = '[$indicator]($style)'
fish_indicator = ''
zsh_indicator = 'z'
[sudo]
disabled = false

View file

@ -0,0 +1,8 @@
{
cli = import ./cli/cli.nix;
firefox = import ./firefox/firefox.nix;
git = import ./git/git.nix;
ops = import ./ops/ops.nix;
tmux = import ./tmux/tmux.nix;
vim = import ./vim/vim.nix;
}

View file

@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.feature.firefox;
in
{
options.feature.firefox = {
enable = lib.mkEnableOption "Set up firefox";
};
config = lib.mkIf cfg.enable {
programs.firefox = {
enable = true;
# Firefox is expected to be installed as a system package
package = null;
profiles.irl = {
extensions = {
force = true;
packages = with pkgs.nur.repos.rycee.firefox-addons; [
bitwarden
kagi-search
privacy-badger
recap
];
};
settings = {
"browser.newtabpage.activity-stream.discoverystream.sendToPocket.enabled" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredCheckboxes" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"browser.search.suggest.enabled.private" = false;
"datareporting.policy.firstRunURL" = "https://irl.xyz/";
"extensions.autoDisableScope" = 0;
"extensions.pocket.enabled" = false;
"identity.fxaccounts.enabled" = false;
};
};
};
};
}

View file

@ -0,0 +1,41 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.feature.git;
in
{
options.feature.git.enable = lib.mkEnableOption "Set up git";
config = {
programs.git = {
delta.enable = true;
enable = true;
extraConfig = {
diff = {
algorithm = "histogram";
};
init = {
defaultBranch = "main";
};
rebase = {
autosquash = true;
autostash = true;
};
url = {
"git@github.com:".pushInsteadOf = "https://github.com/";
"git@gitlab.com:".pushInsteadOf = "https://gitlab.com/";
"git@guardianproject.dev:".pushInsteadOf = "https://guardianproject.dev/";
};
user = {
name = "irl";
email = "iain@learmonth.me";
};
};
};
};
}

View file

@ -0,0 +1,22 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.feature.ops;
in
{
options.feature.ops = {
enable = lib.mkEnableOption "Setup DevOps tools";
};
config = lib.mkIf cfg.enable {
home.packages = with pkgs; [
age
awscli2
opentofu
];
};
}

View file

View file

@ -0,0 +1,25 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.feature.tmux;
in
{
options.feature.tmux = {
enable = lib.mkEnableOption "Set up tmux";
};
config = lib.mkIf cfg.enable {
programs.tmux = {
enable = true;
baseIndex = 1;
plugins = with pkgs.tmuxPlugins; [
catppuccin
];
extraConfig = builtins.readFile ./tmux.conf;
};
};
}

View file

@ -0,0 +1,29 @@
-- Global settings
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.g.mapleader = " "
vim.opt.termguicolors = true
vim.opt.expandtab = true
vim.cmd.colorscheme "catppuccin"
-- Custom bindings
vim.keymap.set("n", "<leader>n", "<cmd>bn<CR>", { noremap = true, silent = true })
vim.keymap.set("n", "<leader>p", "<cmd>bp<CR>", { noremap = true, silent = true })
-- Bufferline (tabs)
require("bufferline").setup{}
-- Lualine (status line)
require("lualine").setup{}
-- Telescope (anything search)
vim.keymap.set("n", "<leader>b", "<cmd>Telescope buffers<CR>", { noremap = true, silent = true })
vim.keymap.set("n", "<leader>f", "<cmd>Telescope find_files<CR>", { noremap = true, silent = true })
-- lspconfig (LSPs)
vim.lsp.enable("nil")
vim.lsp.enable("pyright")
vim.lsp.enable("rust-analyzer")

View file

@ -0,0 +1,39 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.feature.vim;
in
{
options.feature.vim = {
enable = lib.mkEnableOption "Set up neovim";
};
config = lib.mkIf cfg.enable {
home.packages = with pkgs; [
nil
pyright
rust-analyzer
];
programs.neovim = {
defaultEditor = true;
enable = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
plugins = with pkgs.vimPlugins; [
bufferline-nvim
catppuccin-nvim
lualine-nvim
nvim-lspconfig
telescope-nvim
nvim-web-devicons
];
extraLuaConfig = builtins.readFile ./init.lua;
};
};
}