Upgraded snowfall lib

This commit is contained in:
Alejandro Angulo 2023-10-04 20:36:21 -07:00
parent 7e87dbc55b
commit a1709f033f
Signed by: alejandro-angulo
GPG key ID: 75579581C74554B6
58 changed files with 22 additions and 19 deletions

View file

@ -0,0 +1,23 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.bat;
in {
options.aa.apps.bat = with types; {
enable = mkEnableOption "bat";
};
config = mkIf cfg.enable {
aa.home.extraOptions = {
programs.bat = {
enable = true;
config.theme = "gruvbox-dark";
};
};
};
}

View file

@ -0,0 +1,25 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.apps.btop;
in {
options.aa.apps.btop = with types; {
enable = mkEnableOption "btop";
};
config = mkIf cfg.enable {
aa.home.extraOptions.programs.btop = {
enable = true;
settings = {
theme_background = false;
vim_keys = true;
color_theme = "gruvbox_dark_v2";
};
};
};
}

View file

@ -0,0 +1,16 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.firefox;
in {
options.aa.apps.firefox = with types; {
enable = mkEnableOption "firefox";
};
config = mkIf cfg.enable {environment.systemPackages = with pkgs; [firefox];};
}

View file

@ -0,0 +1,388 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.neovim;
in {
options.aa.apps.neovim = with types; {
enable = mkEnableOption "neovim";
tmuxThemePath = mkOption {
type = str;
default = "vim-tmuxline/tmux_theme";
description = "Where to store tmux theme generated by vim-tmuxline";
};
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [fzf fd nixd];
aa.home.dataFile = {
${cfg.tmuxThemePath}.source = ./tmux_theme;
};
aa.home.extraOptions = {
programs.neovim = {
enable = true;
withNodeJs = true;
withPython3 = true;
extraPython3Packages = ps: with ps; [black isort flake8 ipdb];
#extraPackages = with pkgs; [];
plugins = with pkgs.vimPlugins; [
# tree-sitter (code parser)
(nvim-treesitter.withPlugins (_: pkgs.tree-sitter.allGrammars))
# git integration
gitgutter
fugitive
rhubarb
# coc plugins
coc-json
coc-yaml
coc-pyright
coc-spell-checker
coc-rust-analyzer
# Eye candy
nvim-web-devicons
# base16-vim
nvim-base16
markdown-preview-nvim
{
plugin = lualine-nvim;
type = "lua";
config = ''
require('lualine').setup {
options = {
icons_enabled = true,
theme = 'auto',
component_separators = { left = '', right = ''},
section_separators = { left = '', right = ''},
disabled_filetypes = {
statusline = {},
winbar = {},
},
ignore_focus = {},
always_divide_middle = true,
globalstatus = false,
refresh = {
statusline = 1000,
tabline = 1000,
winbar = 1000,
}
},
sections = {
lualine_a = {'mode'},
lualine_b = {'branch', 'diff', 'diagnostics'},
lualine_c = {'filename'},
lualine_x = {'encoding', 'fileformat', 'filetype'},
lualine_y = {'progress'},
lualine_z = {'location'}
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = {'filename'},
lualine_x = {'location'},
lualine_y = {},
lualine_z = {}
},
tabline = {},
winbar = {},
inactive_winbar = {},
extensions = {}
}
'';
}
# TODO: Only install these if tmux is enabled
# tmux integration
tmux-navigator
tmuxline-vim
vim-obsession
vim-nix
# Telescope (fuzzy finding)
telescope-nvim # Config for this in `extraConfig` since it depends on <leader> and I override that. (Generated config places plugin config above contents of extraConfig
{
plugin = telescope-file-browser-nvim;
type = "lua";
config = ''
vim.api.nvim_set_keymap(
"n",
"<space>fb",
":Telescope file_browser<CR>",
{ noremap = true }
)
require("telescope").load_extension("file_browser")
'';
}
{
plugin = telescope-coc-nvim;
type = "lua";
config = ''
require("telescope").setup({
extensions = {
coc = {
prefer_locations = true;
}
}
})
require("telescope").load_extension("coc")
vim.api.nvim_set_keymap(
"n",
"<leader>coc",
":Telescope coc<CR>",
{ noremap = true }
)
'';
}
];
coc = {
enable = true;
settings = {
"coc.preferences.formatOnSave" = true;
"python.formatting.provider" = "black";
"languageserver" = {
"nixd" = {
"command" = "nixd";
"rootPatterns" = [".nixd.json"];
"filetypes" = ["nix"];
};
};
};
# Copied the below from coc's README
pluginConfig =
''
" Some servers have issues with backup files, see #649.
set nobackup
set nowritebackup
" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
" delays and poor user experience.
set updatetime=300
" Always show the signcolumn, otherwise it would shift the text each time
" diagnostics appear/become resolved.
set signcolumn=yes
" Use tab for trigger completion with characters ahead and navigate.
" NOTE: There's always complete item selected by default, you may want to enable
" no select by `"suggest.noselect": true` in your configuration file.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
\ coc#pum#visible() ? coc#pum#next(1) :
\ CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u breaks current undo, please make your own choice.
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
function! CheckBackspace() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" Use <c-space> to trigger completion.
if has('nvim')
inoremap <silent><expr> <c-space> coc#refresh()
else
inoremap <silent><expr> <c-@> coc#refresh()
endif
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window.
nnoremap <silent> K :call ShowDocumentation()<CR>
function! ShowDocumentation()
if CocAction('hasProvider', 'hover')
call CocActionAsync('doHover')
else
call feedkeys('K', 'in')
endif
endfunction
" Highlight the symbol and its references when holding the cursor.
autocmd CursorHold * silent call CocActionAsync('highlight')
" Symbol renaming.
nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code.
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s).
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
" Update signature help on jump placeholder.
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end
" Applying codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf <Plug>(coc-fix-current)
" Run the Code Lens action on the current line.
nmap <leader>cl <Plug>(coc-codelens-action)
" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)
" Remap <C-f> and <C-b> for scroll float windows/popups.
if has('nvim-0.4.0') || has('patch-8.2.0750')
nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
endif
" Use CTRL-S for selections ranges.
" Requires 'textDocument/selectionRange' support of language server.
nmap <silent> <C-s> <Plug>(coc-range-select)
xmap <silent> <C-s> <Plug>(coc-range-select)
" Add `:Format` command to format current buffer.
command! -nargs=0 Format :call CocActionAsync('format')
" Add `:Fold` command to fold current buffer.
command! -nargs=? Fold :call CocAction('fold', <f-args>)
" Add `:OR` command for organize imports of the current buffer.
command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
" Add (Neo)Vim's native statusline support.
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline.
set statusline^=%{coc#status()}%{get(b:,'coc_current_function',''
+ "''"
+ '' )}
" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
''
# The below is custom and did not come from coc's README
+ ''
" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gs :call CocAction('jumpDefinition', 'split')<CR>
nmap <silent> gv :call CocAction('jumpDefinition', 'vsplit')<CR>
nmap <silent> gn :call CocAction('jumpDefinition', 'tabe')<CR>
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
'';
};
extraConfig = ''
set tabstop=4
set shiftwidth=4
set mouse=a
set expandtab
set number
set relativenumber
set autoindent
syntax on
let mapleader = "`"
" Eye Candy (selects theme and sets up transparency)
colorscheme base16-darktooth
hi Normal guibg=none ctermbg=none
hi NormalNC guibg=NONE
hi LineNr guibg=none ctermbg=none
hi Folded guibg=none ctermbg=none
hi NonText guibg=none ctermbg=none
hi SpecialKey guibg=none ctermbg=none
hi VertSplit guibg=none ctermbg=none
hi SignColumn guibg=none ctermbg=none
hi EndOfBuffer guibg=none ctermbg=none
" Toggle line highlighting based on focus
autocmd BufEnter * setlocal cursorline
autocmd BufLeave * setlocal nocursorline
" Toggle relative line numbers
nmap <leader>num :set invrelativenumber<CR>
" Bindings for telescope-nvim
nnoremap <leader>ff <cmd>lua require('telescope.builtin').find_files()<cr>
nnoremap <leader>fg <cmd>lua require('telescope.builtin').live_grep()<cr>
nnoremap <leader>fb <cmd>lua require('telescope.builtin').buffers()<cr>
nnoremap <leader>fh <cmd>lua require('telescope.builtin').help_tags()<cr>
" coc
nnoremap <Leader>cmd :CocCommand<CR>
nnoremap <Leader>cfg :CocConfig<CR>
nnoremap <Leader>def :call CocAction('jumpDefinition')<CR>
nnoremap <Leader>fmt :call CocActionAsync('format')<CR>
vmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" rhubarb
noremap <Leader>bro :GBrowse<CR>
" Tab completion
set wildmode=longest,list,full
set wildmenu
'';
};
};
};
}

View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
# Generates a tmux statusline theme based off the theme in neovim
# May require some edits
nvim -c ":Tmuxline vim_statusline_1 | TmuxlineSnapshot! $(dirname "$0")/tmux_theme | qa!"

View file

@ -0,0 +1,22 @@
# This tmux statusbar config was created by tmuxline.vim
# on Sun, 02 Apr 2023
# Some modifications made by hand
set -g status-justify "left"
set -g status "on"
set -g status-left-style "none"
set -g message-command-style "fg=#a89984,bg=#504945"
set -g status-right-style "none"
set -g pane-active-border-style "fg=#504945"
set -g status-style "none,bg=#32302f"
set -g message-style "fg=#a89984,bg=#504945"
set -g pane-border-style "fg=#32302f"
set -g status-right-length "100"
set -g status-left-length "100"
setw -g window-status-activity-style "none"
setw -g window-status-separator ""
setw -g window-status-style "none,fg=#928374,bg=#32302f"
set -g status-left "#[fg=#928374,bg=#32302f] #S #[fg=#32302f,bg=#32302f,nobold,nounderscore,noitalics]"
set -g status-right "#[fg=#32302f,bg=#32302f,nobold,nounderscore,noitalics]#[fg=#928374,bg=#32302f] %Y-%m-%d  %H:%M #[fg=#32302f,bg=#32302f,nobold,nounderscore,noitalics]#[fg=#928374,bg=#32302f] #h "
setw -g window-status-format "#[fg=#928374,bg=#32302f] #I )#[fg=#928374,bg=#32302f] #W "
setw -g window-status-current-format "#[fg=#32302f,bg=#504945,nobold,nounderscore,noitalics]#[fg=#a89984,bg=#504945] #I #[fg=#a89984,bg=#504945] #W #[fg=#504945,bg=#32302f,nobold,nounderscore,noitalics]"

View file

@ -0,0 +1,36 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.steam;
in {
options.aa.apps.steam = with types; {
enable = mkEnableOption "steam";
};
config = mkIf cfg.enable {
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
};
hardware.opengl = {
enable = true;
driSupport = true;
driSupport32Bit = true;
};
# TODO: This can be removed when/if PR 189398 is merged
# https://github.com/NixOS/nixpkgs/pull/189398
aa.home.extraOptions = {
home.sessionVariables = {
STEAM_EXTRA_COMPAT_TOOLS_PATHS = "${pkgs.aa.proton-ge-custom}";
};
};
};
}

View file

@ -0,0 +1,88 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.tmux;
user_cfg = config.home-manager.users.${config.aa.user.name};
in {
options.aa.apps.tmux = with types; {
enable = mkEnableOption "tmux";
};
config = mkIf cfg.enable {
aa.home.extraOptions = {
programs.tmux = {
enable = true;
keyMode = "vi";
newSession = true;
sensibleOnTop = true;
terminal = "screen-256color";
# TOOD: Check if neovim is enabled before config vim integrations
plugins = with pkgs.tmuxPlugins; [
{
plugin = resurrect;
extraConfig = ''
set -g @resurrect-capture-pane-contents 'on'
set -g @resurrect-strategy-vim 'session'
'';
}
vim-tmux-navigator
];
extraConfig =
''
# Color fix
# set-option -ga terminal-overrides ",alacritty:Tc,xterm-256color:Tc"
# Scrolling with mouse wheel scrolls output instead of previous commands
setw -g mouse on
# Open panes in the same directory
bind c new-window -c "#{pane_current_path}"
bind '"' split-window -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"
# Eye Candy
# set -g @plugin 'mattdavis90/base16-tmux'
# set -g @colors-base16 'darktooth'
# Smart pane switching with awareness of Vim splits.
# See: https://github.com/christoomey/vim-tmux-navigator
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?\\.?g?(view|n?vim?x?)(-wrapped)?(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'
if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \
"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'"
if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \
"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'"
bind-key -T copy-mode-vi 'C-h' select-pane -L
bind-key -T copy-mode-vi 'C-j' select-pane -D
bind-key -T copy-mode-vi 'C-k' select-pane -U
bind-key -T copy-mode-vi 'C-l' select-pane -R
bind-key -T copy-mode-vi 'C-\' select-pane -l
''
+ (
if config.aa.apps.neovim.enable
then ''
# Integration with tmuxline.vim
source-file ${user_cfg.xdg.dataHome}/${config.aa.apps.neovim.tmuxThemePath}
''
else ""
);
};
};
};
}

View file

@ -0,0 +1,37 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.apps.yubikey;
in {
options.aa.apps.yubikey = with types; {
enable = mkEnableOption "yubikey";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [
yubikey-manager
yubikey-agent
yubico-pam
age-plugin-yubikey
rage
];
services.pcscd.enable = true;
security.pam.yubico = {
enable = true;
#debug = true;
mode = "challenge-response";
# Uncomment below for 2FA
#control = "required";
};
# To set up, need to run (might need to run first command as root)
# ykman otp chalresp --touch --generate 2
# ykpamcfg -2 -v
};
}

View file

@ -0,0 +1,24 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.archetypes.workstation;
in {
options.aa.archetypes.workstation = with types; {
enable = mkEnableOption "workstation archetype";
};
config = mkIf cfg.enable {
aa = {
suites = {
desktop.enable = true;
development.enable = true;
utils.enable = true;
};
};
};
}

View file

@ -0,0 +1,51 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.addons.alacritty;
in {
options.aa.desktop.addons.alacritty = with types; {
enable = mkEnableOption "alacritty";
};
config = mkIf cfg.enable {
aa.system.fonts.enable = true;
# alacritty won't start without opengl
hardware.opengl.enable = true;
aa.home = {
extraOptions = {
programs.alacritty = {
enable = true;
settings = {
window.opacity = 0.95;
font = {
size = 12.0;
normal = {
family = "Hack Nerd Font";
style = "Regular";
};
bold = {
family = "Hack Nerd Font";
style = "Bold";
};
italic = {
family = "Hack Nerd Font";
style = "Italic";
};
bold_italic = {
family = "Hack Nerd Font";
style = "Bold Italic";
};
};
};
};
};
};
};
}

View file

@ -0,0 +1,25 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.addons.gammastep;
in {
options.aa.desktop.addons.gammastep = with types; {
enable = mkEnableOption "gammastep";
};
config = mkIf cfg.enable {
services.geoclue2.enable = true;
aa.home.extraOptions = {
services.gammastep = {
enable = true;
provider = "geoclue2";
};
};
};
}

View file

@ -0,0 +1,35 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.addons.mako;
in {
options.aa.desktop.addons.mako = with types; {
enable = mkEnableOption "mako";
};
config = mkIf cfg.enable {
aa.system.fonts.enable = true;
environment.systemPackages = with pkgs; [mako libnotify];
aa.home.extraOptions = {
services.mako = {
enable = true;
font = "'Hack Nerd Font' Regular 9";
backgroundColor = "#1D2021F0";
textColor = "#FFFFDF";
borderColor = "#1C1C1C";
borderRadius = 10;
padding = "10";
};
};
};
}

View file

@ -0,0 +1,22 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.addons.playerctl;
in {
options.aa.desktop.addons.playerctl = with types; {
enable = mkEnableOption "playerctl";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [playerctl];
aa.home.extraOptions = {
services.playerctld.enable = true;
};
};
}

View file

@ -0,0 +1,27 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.desktop.addons.rofi;
in {
options.aa.desktop.addons.rofi = with types; {
enable = mkEnableOption "rofi";
};
config = mkIf cfg.enable {
aa.home.extraOptions = {
programs.rofi = {
enable = true;
font = "Hack Nerd Font 10";
theme = "gruvbox-dark-hard";
extraConfig = {
show-icons = true;
};
};
};
};
}

View file

@ -0,0 +1,41 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.addons.swayidle;
in {
options.aa.desktop.addons.swayidle = with types; {
enable = mkEnableOption "swayidle";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [swayidle];
aa.home.extraOptions = {
services.swayidle = {
enable = true;
timeouts = [
{
timeout = 300;
command = "${pkgs.swaylock}/bin/swaylock";
}
{
timeout = 600;
command = "${pkgs.sway}/bin/swaymsg 'output * dpms off'";
resumeCommand = "${pkgs.sway}/bin/swaymsg 'output * dpms on'";
}
];
events = [
{
event = "before-sleep";
command = "${pkgs.swaylock}/bin/swaylock";
}
];
};
};
};
}

View file

@ -0,0 +1,29 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.addons.swaylock;
user_cfg = config.home-manager.users.${config.aa.user.name};
in {
options.aa.desktop.addons.swaylock = with types; {
enable = mkEnableOption "swaylock";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [swaylock];
aa.home.extraOptions = {
programs.swaylock.settings = {
image = "${user_cfg.xdg.dataHome}/${config.aa.desktop.sway.wallpaperPath}";
};
};
# Workaround for https://github.com/NixOS/nixpkgs/issues/158025
# This comment specifically: https://github.com/NixOS/nixpkgs/issues/158025#issuecomment-1344766809
security.pam.services.swaylock = {};
};
}

View file

@ -0,0 +1,155 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.desktop.addons.waybar;
in {
options.aa.desktop.addons.waybar = with types; {
enable = mkEnableOption "waybar";
thermal-zone = mkOption {
type = int;
default = 0;
description = "The thermal zone, as in `/sys/class/thermal/`.";
};
};
config = mkIf cfg.enable {
aa.system.fonts.enable = true;
aa.home = {
extraOptions = {
programs.waybar = {
enable = true;
systemd.enable = true;
style = builtins.readFile ./waybar_style.css;
settings = [
{
layer = "top";
position = "bottom";
height = 20;
modules-left = ["sway/workspaces"];
modules-center = ["clock"];
modules-right = [
"idle_inhibitor"
"temperature"
"cpu"
"pulseaudio"
"battery"
"memory"
"backlight"
"network"
"tray"
];
"sway/workspaces" = {
disable-scroll = false;
all-outputs = true;
format = "{icon}";
format-icons = {
"1" = "q";
"2" = "w";
"3" = "e";
"4" = "r";
"5" = "t";
"6" = "y";
"7" = "u";
"8" = "i";
"9" = "o";
};
};
idle_inhibitor = {
format = "{icon}";
format-icons = {
activated = " ";
deactivated = " ";
};
};
temperature = {
critical-threshold = 80;
format = "{icon}{temperatureC}°C";
format-icons = [" " " " " "];
thermal-zone = cfg.thermal-zone;
};
cpu = {
format = " {usage}%";
tooltip = false;
};
pulseaudio = {
format = "{icon} {volume}% {format_source}";
format-bluetooth = "{icon} {volume}% {format_source}";
format-bluetooth-muted = " {volume}% {format_source}";
format-muted = " {format_source}";
format-source = " ";
format-source-muted = " ";
format-icons = {
headphone = " ";
hands-free = " ";
headset = " ";
phone = " ";
portable = " ";
car = " ";
default = [" " " " " "];
};
tooltip-format = "{desc}, {volume}%";
# TODO: Figure out how to get pactl binary?
on-click = "pactl set-sink-mute @DEFAULT_SINK@ toggle";
on-click-right = "pactl set-source-mute @DEFAULT_SOURCE@ toggle";
on-click-middle = "pavucontrol";
};
battery = {
states = {
warning = 30;
critical = 1;
};
format = "{icon} {capacity}%";
tooltip-format = "{timeTo}, {capacity}%";
format-charging = "󰂄 {capacity}%";
format-plugged = " ";
format-alt = "{time} {icon}";
format-icons = [" " " " " " " " " "];
};
memory = {
format = " {}%";
};
backlight = {
format = "{icon} {percent}%";
format-icons = ["󰃞`" "󰃚"];
on-scroll-up = "light -A 1";
on-scroll-down = "light -U 1";
};
network = {
format-wifi = " ";
format-ethernet = "{ifname}: {ipaddr}/{cidr} 󰈀 ";
format-linked = "{ifname} (No IP) ";
format-disconnected = " ";
format-alt = "{ifname}: {ipaddr}/{cidr}";
tooltip-format = "{essid} {signalStrength}%";
};
tray = {
spacing = 10;
};
}
];
};
wayland.windowManager.sway.config.bars = [];
};
};
};
}

View file

@ -0,0 +1,132 @@
* {
border: none;
font-family: Hack Nerd Font, sans-serif;
font-size: 1em;
}
window#waybar {
background-color: rgba(29, 32, 33, 0.9);
border-bottom: 3px solid #1d2021;
color: #ffffdf;
transition-property: background-color;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
#workspaces,
#mode,
#cpu,
#memory,
#temperature,
#clock,
#idle_inhibitor,
#language,
#pulseaudio,
#backlight,
#battery,
#network,
#tray {
background-color: #303030;
padding: 0 10px;
margin: 3px;
border: 3px solid rgba(0, 0, 0, 0);
border-radius: 90px;
background-clip: padding-box;
}
#workspaces button {
padding: 0 5px;
min-width: 20px;
color: #87afaf;
}
#workspaces button:hover {
background-color: rgba(0, 0, 0, 1)
}
#workspaces button.focused {
color: #ffaf00;
}
#workspaces button.urgent {
color: #e06c75;
}
#clock {
color: #61afef;
}
#idle_inhibitor {
color: #abb2bf;
}
#idle_inhibitor.activated {
background-color: #abb2bf;
color: #1e222a;
}
#temperature {
color: #fb4934;
}
#temperature.critical {
color: #1d2021;
background-color: #9d0006;
}
#cpu {
color: #ff8700;
}
#memory {
color: #87af87;
}
#battery {
color: #b8bb26;
}
#battery.charging, #battery.plugged {
background-color: #1f321c;
color: #ffffaf;
}
@keyframes blink {
to {
background-color: #1f321c;
color: #ffffaf;
}
}
#battery.critical:not(.charging) {
background-color: #afaf00;
color: #303030;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#pulseaudio {
color: #fabd2f;
}
#pulseaudio.muted {
color: #b57614;
}
#backlight {
color: #17ccd5;
}
#network {
color: #d787af;
}
#network.disconnected {
color: #875f87;
}

View file

@ -0,0 +1,319 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.desktop.sway;
user_cfg = config.home-manager.users.${config.aa.user.name};
nag = "swaynag";
left = "h";
right = "l";
up = "k";
down = "j";
modifier = "Mod4";
# TODO: This assume I'll be using rofi and alacritty. Should make more
# generic.
menu = "rofi -show run";
terminal = "alacritty";
generate_grimshot_command = target: ''exec mkdir -p ~/screenshots && ${pkgs.sway-contrib.grimshot}/bin/grimshot --notify save ${target} ~/screenshots/"$(date -u --iso-8601=seconds)".png'';
in {
options.aa.desktop.sway = with types; {
enable = mkEnableOption "sway";
wallpaperPath = mkOption {
type = str;
default = "sway/wallpaper.jpg";
description = ''
Path to wallpaper, relative to config.home-home-manager.users.<username>.xdg.dataHome
'';
};
verticalWallpaperPath = mkOption {
type = str;
default = "sway/skull.png";
description = ''
Path to vertical wallpaper, relative to config.home-home-manager.users.<username>.xdg.dataHome
'';
};
};
config = mkIf cfg.enable {
aa.desktop.addons = {
alacritty.enable = true;
gammastep.enable = true;
mako.enable = true;
playerctl.enable = true;
rofi.enable = true;
swayidle.enable = true;
swaylock.enable = true;
waybar.enable = true;
# TODO
# light
};
aa.system.fonts.enable = true;
environment.systemPackages = with pkgs; [
wl-clipboard
grim
slurp
xdg-utils
xdg-desktop-portal-wlr
sway-contrib.grimshot
wev
];
# For screen sharing to work
xdg.portal = {
enable = true;
extraPortals = with pkgs; [xdg-desktop-portal-gtk];
wlr.enable = true;
};
aa.home.dataFile = {
${cfg.wallpaperPath}.source = ./wallpaper.jpg;
${cfg.verticalWallpaperPath}.source = ./vertical.png;
};
aa.home.extraOptions = {
wayland.windowManager.sway = {
enable = true;
swaynag.enable = true;
wrapperFeatures.gtk = true; # so that gtk works properly
systemd.enable = true; # needed this for screen sharing to work
config = {
inherit (terminal menu left right up down modifier);
workspaceAutoBackAndForth = true;
colors = {
focused = {
border = "#2B3C44";
background = "#4E3D45";
text = "#FFFFFF";
indicator = "#333333";
childBorder = "#000000";
};
focusedInactive = {
border = "#484848";
background = "#333333";
text = "#FFFFFF";
indicator = "#000000";
childBorder = "#000000";
};
unfocused = {
border = "#484848";
background = "#333333";
text = "#FFFFFF";
indicator = "#000000";
childBorder = "#000000";
};
};
window = {
titlebar = true;
commands = [
{
command = "inhibit_idle fullscreen";
criteria = {class = ".*";};
}
];
};
focus.followMouse = false;
fonts = {
names = ["Hack Nerd Font"];
size = 10.0;
};
# TODO: Should this live at the system configuration level?
output = {
# TODO: Set up wallpaper
"*".bg = "${user_cfg.xdg.dataHome}/${cfg.wallpaperPath} fill";
"eDP-1".scale = "1.25";
"ASUSTek COMPUTER INC ASUS VG24V 0x00007AAC" = {
mode = "1920x1080@120Hz";
position = "0 830";
};
"Dell Inc. DELL S2721QS 47W7M43" = {
transform = "270";
position = "1920 0";
bg = "${user_cfg.xdg.dataHome}/${cfg.verticalWallpaperPath} fill";
};
"Dell Inc. DELL S2721QS 4FR7M43".position = "4080 830";
};
modes = {
resize = {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
"${left}" = "resize shrink width 50px";
"${down}" = "resize grow height 50px";
"${up}" = "resize shrink height 50px";
"${right}" = "resize grow width 50px";
# Ditto, with arrow keys
"Left" = "resize shrink width 50px";
"Down" = "resize grow height 50px";
"Up" = "resize shrink height 50px";
"Right" = "resize grow width 50px";
# Exit resize mode
"Insert" = "mode default";
"Escape" = "mode default";
"Return" = "mode default";
};
nag = {
"Ctrl+d" = "mode default";
"Ctrl+c" = "exec ${nag} --exit";
"q" = "exec ${nag} --exit";
"Escape" = "exec ${nag} --exit";
"Return" = "exec ${nag} --confirm";
"j" = "exec ${nag} --next";
"Tab" = "exec ${nag} --next";
"Up" = "exec ${nag} --next";
"k" = "exec ${nag} --prev";
"Shift+Tab" = "exec ${nag} prev";
"Down" = "exec ${nag} prev";
};
};
keybindings = {
# Activate modes
"${modifier}+s" = "mode resize";
# Misc
"${modifier}+Return" = "exec ${terminal}";
"${modifier}+c" = "kill";
"${modifier}+p" = "exec ${menu}";
"${modifier}+z" = "reload";
"${modifier}+x" = "exec swaylock";
# Volume control
"XF86AudioRaiseVolume" = " exec 'pamixer --increase 5'";
"XF86AudioLowerVolume" = " exec 'pamixer --decrease 5'";
"XF86AudioMute" = " exec 'pamixer --toggle-mute'";
# Music player control
"XF86AudioPrev" = "exec 'playerctl previous'";
"XF86AudioNext" = "exec 'playerctl next'";
"XF86AudioPlay" = "exec 'playerctl play-pause'";
"${modifier}+Down" = "exec 'playerctl pause'";
"${modifier}+Up" = "exec 'playerctl play'";
"${modifier}+Right" = "exec 'playerctl next'";
"${modifier}+Left" = "exec 'playerctl previous'";
# Backlight keys
"XF86MonBrightnessDown" = "exec 'light -U 5'";
"XF86MonBrightnessUp" = "exec 'light -A 5'";
# Navigation
## Focus
### Move your focus around
"${modifier}+${left}" = "focus left";
"${modifier}+${down}" = "focus down";
"${modifier}+${up}" = "focus up";
"${modifier}+${right}" = "focus right";
### Move the focused window with the same, but add Shift
"${modifier}+Shift+${left}" = "move left";
"${modifier}+Shift+${down}" = "move down";
"${modifier}+Shift+${up}" = "move up";
"${modifier}+Shift+${right}" = "move right";
## Workspaces
### Switch to a workspace
"${modifier}+q" = "workspace number 1";
"${modifier}+w" = "workspace number 2";
"${modifier}+e" = "workspace number 3";
"${modifier}+r" = "workspace number 4";
"${modifier}+t" = "workspace number 5";
"${modifier}+y" = "workspace number 6";
"${modifier}+u" = "workspace number 7";
"${modifier}+i" = "workspace number 8";
"${modifier}+o" = "workspace number 9";
### Move focused container to workspace
"${modifier}+Shift+q" = "move container to workspace number 1";
"${modifier}+Shift+w" = "move container to workspace number 2";
"${modifier}+Shift+e" = "move container to workspace number 3";
"${modifier}+Shift+r" = "move container to workspace number 4";
"${modifier}+Shift+t" = "move container to workspace number 5";
"${modifier}+Shift+y" = "move container to workspace number 6";
"${modifier}+Shift+u" = "move container to workspace number 7";
"${modifier}+Shift+i" = "move container to workspace number 8";
"${modifier}+Shift+o" = "move container to workspace number 9";
# Layout
## Split direction
"${modifier}+v" = "splith";
"${modifier}+g" = "splitv";
## Switch the current container between different layout styles
"${modifier}+b" = "layout stacking";
"${modifier}+n" = "layout tabbed";
"${modifier}+m" = "layout toggle split";
## Make the current focus fullscreen
"${modifier}+f" = "fullscreen";
## move container between displays
"${modifier}+semicolon" = "move workspace to output right";
## Toggle the current focus between tiling and floating mode
"${modifier}+Shift+f" = "floating toggle";
## Swap focus between the tiling area and the floating area
"${modifier}+space" = "focus mode_toggle";
## Move focus to the parent container
"${modifier}+a" = "focus parent";
# Screenshots
## Current window
"${modifier}+period" = generate_grimshot_command "active";
## Area selection
"${modifier}+Shift+period" = generate_grimshot_command "area";
## Current output
"${modifier}+Alt+period" = generate_grimshot_command "output";
## Window selection
"${modifier}+Ctrl+period" = generate_grimshot_command "window";
# Scratchpad
# Move the currently focused window to the scratchpad
"${modifier}+Shift+minus" = "move scratchpad";
# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
"${modifier}+minus" = "scratchpad show";
# Exit sway (logs you out of your Wayland session)
"${modifier}+Shift+z" = "exec ${nag} -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' -b 'Reload' 'swaymsg reload'";
};
};
};
};
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

View file

@ -0,0 +1,25 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.hardware.audio;
in {
options.aa.hardware.audio = with types; {
enable = mkEnableOption "audio";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [pamixer];
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
};
}

View file

@ -0,0 +1,20 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.hardware.bluetooth;
in {
options.aa.hardware.bluetooth = with types; {
enable = mkEnableOption "bluetooth";
};
config = mkIf cfg.enable {
hardware.bluetooth.enable = true;
services.blueman.enable = true;
};
}

View file

@ -0,0 +1,32 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.hardware.logitech;
in {
options.aa.hardware.logitech = with types; {
enable = mkEnableOption "logitech devices";
};
config = mkIf cfg.enable {
hardware.logitech.wireless = {
enable = true;
enableGraphical = true;
};
systemd.user.services.solaar = {
description = "Linux device manager for Logitech devices";
documentation = ["https://pwr-solaar.github.io/Solaar/"];
partOf = ["graphical-session.target"];
serviceConfig = {
Type = "simple";
ExecStart = "${pkgs.solaar}/bin/solaar -w hide";
};
};
systemd.user.services.solaar.wantedBy = mkIf config.aa.desktop.sway.enable ["sway-session.target"];
};
}

View file

@ -0,0 +1,28 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.hardware.tlp;
in {
options.aa.hardware.tlp = with types; {
enable = mkEnableOption "tlp";
};
config = mkIf cfg.enable {
services.tlp = {
enable = true;
settings = {
START_CHARGE_THRESH_BAT0 = 75;
# Run `tlp setcharge` to temporarily allow charging to 100%
STOP_CHARGE_THRESH_BAT0 = 80;
RESTORE_THRESHOLDS_ON_BAT = 1;
CPU_SCALING_GOVERNOR_ON_AC = "performance";
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
};
};
};
}

View file

@ -0,0 +1,55 @@
{
options,
config,
pkgs,
lib,
inputs,
...
}:
with lib; let
cfg = config.aa.home;
in {
imports = with inputs; [
home-manager.nixosModules.home-manager
];
options.aa.home = with types; {
file = mkOption {
type = attrs;
default = {};
description = "A set of files to be manged by home-manager's <option>home.file</option> option.";
};
configFile = mkOption {
type = attrs;
default = {};
description = "A set of files to be managed by home-manager's <option>xdg.configFile</option>.";
};
dataFile = mkOption {
type = attrs;
default = {};
description = "A set of files to be managed by home-manager's <option>xdg.dataFile</option>.";
};
extraOptions = mkOption {
type = attrs;
default = {};
description = "Options to pass directly to home-manager.";
};
};
config = {
aa.home.extraOptions = {
home.stateVersion = config.system.stateVersion;
home.file = mkAliasDefinitions options.aa.home.file;
xdg.enable = true;
xdg.configFile = mkAliasDefinitions options.aa.home.configFile;
xdg.dataFile = mkAliasDefinitions options.aa.home.dataFile;
};
home-manager = {
useUserPackages = true;
users.${config.aa.user.name} =
mkAliasDefinitions options.aa.home.extraOptions;
};
};
}

View file

@ -0,0 +1,68 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.nix;
selfHostedCacheHost = "https://cache.kilonull.com/";
in {
options.aa.nix = with types; {
enable = mkEnableOption "manage nix configuration.";
package = mkOption {
type = package;
default = pkgs.nixVersions.unstable;
description = "Which nix package to use.";
};
useSelfhostedCache = mkEnableOption "use self-hosted nix cache (currently hosted on gospel)";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [
alejandra
nix-prefetch
];
nix = let
users = ["root" config.aa.user.name];
in {
package = cfg.package;
settings = {
experimental-features = "nix-command flakes";
trusted-users = users;
allowed-users = users;
builders-use-substitutes = cfg.useSelfhostedCache;
substituters =
if cfg.useSelfhostedCache
then [
selfHostedCacheHost
"https://cache.nixos.org/"
]
else [];
trusted-public-keys =
if cfg.useSelfhostedCache
then ["gospelCache:9cbn8Wm54BbwpPS0TXw+15wrYZBpfOJt4Fzfbfcq/pc="]
else [];
};
# TODO: Configure distributedBuilds and buildMachines?
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
# TODO: Not sure if I want this
# flake-utils-plus
# generateRegistryFromInputs = true;
# generateNixPathFromInputs = true;
# linkInputs = true;
};
};
}

View file

@ -0,0 +1,56 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.security.acme;
in {
options.aa.security.acme = with types; {
enable = mkEnableOption "Automatic Certificate Management Environment (ACME)";
useStaging = mkOption {
type = bool;
description = ''
Use the staging environment (use when configuring for the first time to
avoid being locked out).
'';
default = false;
};
domainName = mkOption {
type = str;
description = "The domain to request a wildcard cert for.";
};
dnsCredentialsFile = mkOption {
type = path;
description = "The path to the credentials file for the DNS provider.";
};
};
# Only supports exactly one wildcard cert using Cloudflare (only use case I have)
config = mkIf cfg.enable {
security.acme = {
acceptTerms = true;
defaults = {
email = config.aa.user.email;
group = "nginx";
server = mkIf cfg.useStaging "https://acme-staging-v02.api.letsencrypt.org/directory";
};
# Wildcard cert
certs."${cfg.domainName}" = {
group = "nginx";
dnsProvider = "cloudflare";
# Private network resolves *.kilonull.com to private servers but `lego`
# (acme client under the hood) needs to find the cloudflare nameservers
# to determine the correct zone to apply changes in. Use cloudflare's
# own DNS to make `lego` happy (will resolve names to a public IP).
dnsResolver = "1.1.1.1:53";
credentialsFile = cfg.dnsCredentialsFile;
extraDomainNames = [("*." + cfg.domainName)];
};
};
};
}

View file

@ -0,0 +1,82 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.adguardhome;
in {
options.aa.services.adguardhome = with types; {
enable = mkEnableOption "adguardhome";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
services.adguardhome = {
enable = true;
mutableSettings = true;
settings = {
bind_host = "0.0.0.0";
bind_port = 3000;
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts."adguardhome.kilonull.com" =
{
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall = {
# TODO: Remove this here and leave it up to systems to decide to enable
# the firewall
enable = true;
allowedTCPPorts = [
# Plain DNS
53
# DHCP
68
# HTTP
80
# HTTPS
443
# DNS over TLS
853
# DNSCrypt
5443
];
allowedUDPPorts = [
# Plain DNS
53
# DHCP
67
68
# DNS over QUIC
784
853
8853
# DNSCrypt
5443
];
};
};
}

View file

@ -0,0 +1,74 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.grafana;
server_settings = config.services.grafana.settings.server;
in {
options.aa.services.grafana = with types; {
enable = mkEnableOption "grafana";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
services.grafana = {
enable = true;
settings.server = {
domain = "grafana.kilonull.com";
http_port = 2342;
http_addr = "0.0.0.0";
};
provision = {
enable = true;
datasources = {
# This assumes prometheus, loki, and grafana are all running on the
# same host.
settings.datasources = [
{
name = "Prometheus";
type = "prometheus";
access = "proxy";
url = "http://127.0.0.1:${toString config.services.prometheus.port}";
}
{
name = "Loki";
type = "loki";
access = "proxy";
url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}";
}
];
};
};
};
services.nginx = {
enable = true;
virtualHosts ."${server_settings.domain}" =
{
locations."/" = {
proxyPass = "http://${server_settings.http_addr}:${toString server_settings.http_port}";
proxyWebsockets = true;
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall = {
allowedTCPPorts = [80 443];
};
};
}

View file

@ -0,0 +1,102 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.loki;
loki = config.services.loki;
in {
options.aa.services.loki = with types; {
enable = mkEnableOption "loki";
};
config = mkIf cfg.enable {
services.loki = {
enable = true;
configuration = {
server.http_listen_port = 3030;
auth_enabled = false;
ingester = {
lifecycler = {
address = "127.0.0.1";
ring = {
kvstore = {
store = "inmemory";
};
replication_factor = 1;
};
};
# Any chunk not receiving new logs in this time will be flushed
chunk_idle_period = "1h";
# All chunks will be flushed when they hit this age
max_chunk_age = "1h";
# Loki will attempt to build chunks up to this size, flushing first
# if chunk_idle_period or max_chunk_age is reached first
chunk_target_size = 999999;
chunk_retain_period = "30s";
max_transfer_retries = 0;
};
schema_config = {
configs = [
{
from = "2022-06-06";
store = "boltdb-shipper";
object_store = "filesystem";
schema = "v11";
index = {
prefix = "index_";
period = "24h";
};
}
];
};
storage_config = {
boltdb_shipper = {
active_index_directory = "/var/lib/loki/boltdb-shipper-active";
cache_location = "/var/lib/loki/boltdb-shipper-cache";
cache_ttl = "24h";
shared_store = "filesystem";
};
filesystem = {
directory = "/var/lib/loki/chunks";
};
};
limits_config = {
reject_old_samples = true;
reject_old_samples_max_age = "168h";
};
chunk_store_config = {
max_look_back_period = "0s";
};
table_manager = {
retention_deletes_enabled = false;
retention_period = "0s";
};
compactor = {
working_directory = "/var/lib/loki";
shared_store = "filesystem";
compactor_ring = {
kvstore = {
store = "inmemory";
};
};
};
};
};
networking.firewall = {
allowedTCPPorts = [loki.configuration.server.http_listen_port];
};
};
}

View file

@ -0,0 +1,65 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.nextcloud;
in {
options.aa.services.nextcloud = with types; {
enable = mkEnableOption "nextcloud";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
age.secrets.nextcloud_admin = {
file = ../../../secrets/nextcloud_admin.age;
owner = "nextcloud";
group = "nextcloud";
};
services.nextcloud = {
enable = true;
package = pkgs.nextcloud27;
hostName = "nextcloud.kilonull.com";
https = true;
database.createLocally = true;
datadir = "/tank/nextcloud";
# Arbitrary large size
maxUploadSize = "16G";
configureRedis = true;
logType = "file";
poolSettings = {
pm = "dynamic";
"pm.max_children" = "64";
"pm.max_requests" = "500";
"pm.max_spare_servers" = "25";
"pm.min_spare_servers" = "10";
"pm.start_servers" = "15";
};
config = {
dbtype = "pgsql";
adminuser = "alejandro";
adminpassFile = config.age.secrets.nextcloud_admin.path;
};
};
# nextcloud module configures nginx, just need to specify SSL stuffs here
services.nginx.virtualHosts.${config.services.nextcloud.hostName} = mkIf (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
networking.firewall.allowedTCPPorts = [80 443];
};
}

View file

@ -0,0 +1,70 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.nix-serve;
in {
options.aa.services.nix-serve = with types; {
enable = mkEnableOption "nix-serve";
domain_name = mkOption {
type = str;
description = "The domain to use.";
};
subdomain_name = mkOption {
type = str;
description = "The subdomain to use.";
};
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
nix.settings = {
allowed-users = ["nix-serve"];
trusted-users = ["nix-serve"];
};
environment.systemPackages = [pkgs.nix-serve];
services = {
nix-serve = {
enable = true;
# TODO: Document this or automate the inital creation.
secretKeyFile = "/var/gospelCache";
};
nginx = {
enable = true;
virtualHosts."${cfg.subdomain_name}.${cfg.domain_name}" =
{
serverAliases = ["${cfg.subdomain_name}"];
locations."/".extraConfig = ''
proxy_pass http://localhost:${toString config.services.nix-serve.port};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
};
networking.firewall = {
allowedTCPPorts = [80 443];
};
};
}

View file

@ -0,0 +1,47 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.octoprint;
in {
options.aa.services.octoprint = with types; {
enable = mkEnableOption "octoprint";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, foces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
services.octoprint.enable = true;
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts."octoprint.kilonull.com" =
{
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.octoprint.port}";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 32m;
'';
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall.allowedTCPPorts = [80 443];
};
}

View file

@ -0,0 +1,43 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.openssh;
user = config.users.users.${config.aa.user.name};
user-id = builtins.toString user.uid;
default-key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEmPdQcM0KCQ3YunF1gwN+B+i1Q8KrIfiUvNtgFQjTy2";
in {
options.aa.services.openssh = with types; {
enable = mkEnableOption "ssh";
authorizedKeys = mkOption {
type = listOf str;
default = [default-key];
description = "The public keys to authorize";
};
};
config = mkIf cfg.enable {
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = mkDefault (
if format == "install-iso"
then "yes"
else "no"
);
};
};
aa.user.extraOptions = {
openssh.authorizedKeys.keys = cfg.authorizedKeys;
};
};
}

View file

@ -0,0 +1,23 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.steam;
in {
options.aa.services.printing = with types; {
enable = mkEnableOption "printing";
};
config = mkIf cfg.enable {
# Setup printing over the network
services.printing.enable = true;
services.avahi = {
enable = true;
nssmdns = true;
};
};
}

View file

@ -0,0 +1,59 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.prometheus;
exporters = config.services.prometheus.exporters;
in {
options.aa.services.prometheus = with types; {
enable = mkEnableOption "prometheus";
enableServer = mkOption {
type = bool;
default = false;
description = "Whether or not to enable the prometheus server";
};
enableNodeExporter = mkOption {
type = bool;
default = true;
description = "Whether or not to enable the node exporter";
};
};
config = mkIf cfg.enable {
services.prometheus = {
enable = cfg.enableServer;
exporters = {
node = {
enable = cfg.enableNodeExporter;
enabledCollectors = ["systemd"];
port = 9002;
openFirewall = true;
};
};
scrapeConfigs = mkIf cfg.enableServer [
{
job_name = "node";
static_configs = [
{
# TODO: How to automatically generate this whenever an exporter
# is configured
targets = [
"node:${toString exporters.node.port}"
"gospel:${toString exporters.node.port}"
"pi4:${toString exporters.node.port}"
];
}
];
}
];
};
networking.firewall = mkIf cfg.enableServer {
allowedTCPPorts = [config.services.prometheus.port];
};
};
}

View file

@ -0,0 +1,58 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.promtail;
loki = config.services.loki;
in {
options.aa.services.promtail = with types; {
enable = mkEnableOption "promtail";
};
config = mkIf cfg.enable {
services.promtail = {
enable = true;
configuration = {
server = {
http_listen_port = 28183;
grpc_listen_port = 0;
};
positions = {
filename = "/tmp/positions.yaml";
};
clients = [
{
# TODO: Don't hardcode this?
url = "http://node:3030/loki/api/v1/push";
}
];
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels = {
job = "systemd-journal";
host = config.networking.hostName;
};
};
relabel_configs = [
{
source_labels = ["__journal__systemd_unit"];
target_label = "unit";
}
];
}
];
};
};
# networking.firewall = {
# allowedTCPPorts = [80 443];
# };
};
}

View file

@ -0,0 +1,90 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.services.syncoid;
in {
options.aa.services.syncoid = with types; {
enable = mkEnableOption "syncoid (ZFS snap replication)";
commands = mkOption {
type = attrs;
default = {};
description = "Commands to pass directly to syncoid, see `services.syncoid.commands`";
};
remoteTargetUser = mkOption {
type = str;
default = "";
description = "The user to use on the target machine.";
};
remoteTargetDatasets = mkOption {
type = listOf str;
default = [];
description = "Datasets to be used as a remote target (e.g. a NAS's backups dataset)";
};
remoteTargetPublicKeys = mkOption {
type = listOf str;
default = [];
description = "SSH public keys that the syncoid service's user should trust";
};
};
config = mkIf cfg.enable {
services.syncoid = {
enable = true;
localSourceAllow =
options.services.syncoid.localSourceAllow.default
++ [
"mount"
];
localTargetAllow =
options.services.syncoid.localTargetAllow.default
++ [
"destroy"
];
commands = mkAliasDefinitions options.aa.services.syncoid.commands;
};
environment.systemPackages = mkIf (cfg.remoteTargetUser != "") (with pkgs; [
lzop
mbuffer
]);
users = mkIf (cfg.remoteTargetUser != "") {
users."${cfg.remoteTargetUser}" = {
shell = pkgs.bashInteractive;
group = cfg.remoteTargetUser;
isSystemUser = true;
home = "/var/lib/${cfg.remoteTargetUser}";
createHome = true;
openssh.authorizedKeys.keys = cfg.remoteTargetPublicKeys;
};
groups."${cfg.remoteTargetUser}" = {};
};
systemd.services.setup-syncoid-remote = {
description = "Permission setup for syncoid remote targets";
documentation = ["https://github.com/jimsalterjrs/sanoid/wiki/Syncoid#running-without-root"];
wantedBy = ["multi-user.target"];
path = [pkgs.zfs];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
};
script = ''
DATASETS=(${toString cfg.remoteTargetDatasets})
for dataset in "''${DATASETS[@]}"; do
zfs allow \
-u ${cfg.remoteTargetUser} \
compression,mountpoint,create,mount,receive,rollback,destroy \
"$dataset"
done
'';
};
};
}

View file

@ -0,0 +1,50 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.services.tailscale;
in {
options.aa.services.tailscale = with types; {
enable = mkEnableOption "tailscale";
configureClientRouting = mkOption {
type = bool;
default = false;
description = mdDoc ''
Configures tailscale as a client.
See `options.services.tailscale.useRoutingFeatures` for more information.
'';
};
configureServerRouting = mkOption {
type = bool;
default = false;
description = mdDoc ''
Configures tailscale as a server.
See `options.services.tailscale.useRoutingFeatures` for more information.
'';
};
};
config = mkIf cfg.enable {
environment.systemPackages = [pkgs.tailscale];
networking.firewall.allowedUDPPorts = [config.services.tailscale.port];
services.tailscale = {
enable = true;
useRoutingFeatures = mkIf (cfg.configureClientRouting || cfg.configureServerRouting) (
if (cfg.configureClientRouting && cfg.configureServerRouting)
then "both"
else
(
if cfg.configureClientRouting
then "client"
else "server"
)
);
};
};
}

View file

@ -0,0 +1,26 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.suites.desktop;
in {
options.aa.suites.desktop = with lib.types; {
enable = mkEnableOption "common desktop configuration";
};
config = mkIf cfg.enable {
aa = {
desktop = {
sway.enable = true;
};
apps = {
firefox.enable = true;
};
};
};
}

View file

@ -0,0 +1,35 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.suites.development;
in {
options.aa.suites.development = with lib.types; {
enable = mkEnableOption "common configuration";
};
config = mkIf cfg.enable {
aa = {
tools = {
direnv.enable = true;
eza.enable = true;
git.enable = true;
gpg.enable = true;
zsh.enable = true;
};
apps = {
neovim.enable = true;
tmux.enable = true;
};
};
environment.systemPackages = with pkgs; [
pre-commit
];
};
}

View file

@ -0,0 +1,20 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.suites.gaming;
in {
options.aa.suites.gaming = with lib.types; {
enable = mkEnableOption "gaming configuration";
};
config = mkIf cfg.enable {
aa.apps = {
steam.enable = true;
};
};
}

View file

@ -0,0 +1,41 @@
{
options,
config,
lib,
pkgs,
inputs,
...
}:
with lib; let
cfg = config.aa.suites.utils;
in {
options.aa.suites.utils = with lib.types; {
enable = mkEnableOption "common configuration";
};
config = mkIf cfg.enable {
aa.apps.bat.enable = true;
environment.systemPackages = with pkgs; [
inputs.agenix.packages.x86_64-linux.default
alejandra
bind # for dig
curl
deploy-rs
du-dust
fd
file
htop
jq
killall
lsof
pre-commit
progress
python3
ripgrep
sqlite
tcpdump
usbutils
wget
];
};
}

View file

@ -0,0 +1,23 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.system.fonts;
in {
options.aa.system.fonts = with types; {
enable = mkEnableOption "manage fonts";
};
config = mkIf cfg.enable {
fonts.packages = with pkgs; [
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
(nerdfonts.override {fonts = ["Hack"];})
];
};
}

View file

@ -0,0 +1,27 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.system.monitoring;
in {
options.aa.system.monitoring = with types; {
enable = mkEnableOption "monitoring";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [
htop
lm_sensors
powertop
zenith
];
powerManagement.powertop.enable = true;
aa.apps.btop.enable = true;
};
}

View file

@ -0,0 +1,29 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.system.zfs;
in {
options.aa.system.zfs = with types; {
enable = mkEnableOption "zfs";
# TODO: Introduce a zfsOnRoot option
};
config = mkIf cfg.enable {
environment.systemPackages = [pkgs.zfs-prune-snapshots];
services.zfs = {
autoScrub.enable = true;
# Still need to set `com.sun:auto-snapshot` to `true` on datasets
# zfs set com.sun:auto-snapshot=true pool/dataset
autoSnapshot = {
enable = true;
flags = "-k -p --utc";
};
};
};
}

View file

@ -0,0 +1,23 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.tools.direnv;
in {
options.aa.tools.direnv = with lib.types; {
enable = mkEnableOption "direnv";
};
config = mkIf cfg.enable {
aa.home.extraOptions = {
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
};
};
}

View file

@ -0,0 +1,25 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.tools.eza;
in {
options.aa.tools.eza = with types; {
enable = mkEnableOption "eza";
};
config = mkIf cfg.enable {
aa.home.extraOptions = {
programs.eza = {
enable = true;
icons = true;
git = true;
enableAliases = true;
};
};
};
}

View file

@ -0,0 +1,88 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.tools.git;
gpg = config.aa.tools.gpg;
user = config.aa.user;
in {
options.aa.tools.git = with types; {
enable = mkEnableOption "git";
userName = mkOption {
type = str;
default = user.fullName;
description = "The name to use for git commits.";
};
userEmail = mkOption {
type = str;
default = user.email;
description = "The email to use for git commits.";
};
signingKey = mkOption {
type = str;
default = "0xE1B13CCEFDEDDFB7";
description = "The key ID used to sign commits.";
};
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [git];
aa.home.extraOptions = {
programs.git = {
delta = {
enable = true;
options = {
line-numbers = true;
navigate = true;
};
};
enable = true;
userName = cfg.userName;
userEmail = cfg.userEmail;
aliases = {
lol = "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative";
pushup = "push -u origin HEAD";
};
signing = {
key = cfg.signingKey;
signByDefault = mkIf config.aa.tools.gpg.enable true;
};
ignores = [
# PyCharm
".idea/"
# Vim artifacts
"*.swp"
"*.swo"
"tags"
".vimspector.json"
".vimlocal"
"Session.vim*"
# direnv
".envrc"
".direnv"
];
extraConfig = {
init = {
defaultBranch = "main";
};
pull = {
rebase = true;
};
};
};
};
};
}

View file

@ -0,0 +1,40 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.tools.gpg;
user = config.aa.user;
in {
options.aa.tools.gpg = with types; {
enable = mkEnableOption "gpg";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [gnupg pinentry-curses];
aa.home.extraOptions = {
programs.gpg = {
enable = true;
scdaemonSettings = {
# Fix conflicts with config in common/yubikey.nix
disable-ccid = true;
};
};
services.gpg-agent = {
enable = true;
pinentryFlavor = "curses";
enableZshIntegration = true; # TODO: Only set if using zsh
enableSshSupport = true;
sshKeys = [
# run `gpg-connect-agent 'keyinfo --list' /bye` to get these values for existing keys
"E274D5078327CB6C8C83CFF102CC12A2D493C77F"
];
};
};
};
}

View file

@ -0,0 +1,79 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.tools.zsh;
in {
options.aa.tools.zsh = with types; {
enable = mkEnableOption "zsh";
};
config = mkIf cfg.enable {
# Already set in home-manager below, but without this building fails with
# an assertion error that suggests setting this
programs.zsh.enable = true;
aa.home.extraOptions = {
programs.zsh = {
enable = true;
enableAutosuggestions = true;
enableCompletion = true;
envExtra = ''
export PATH=~/.local/bin:$PATH
export EDITOR=nvim
'';
initExtra = ''
base16_darktooth
bindkey -v
bindkey '^A' beginning-of-line
bindkey '^E' end-of-line
bindkey '^R' history-incremental-search-backward
alias view="nvim -R $1"
alias l='ls -la'
'';
plugins = with pkgs; [
{
name = "zsh-syntax-highlighting";
src = fetchFromGitHub {
owner = "zsh-users";
repo = "zsh-syntax-highlighting";
rev = "0.7.1";
sha256 = "sha256-gOG0NLlaJfotJfs+SUhGgLTNOnGLjoqnUp54V9aFJg8=";
};
file = "zsh-syntax-highlighting.zsh";
}
{
name = "powerlevel10k";
src = fetchFromGitHub {
owner = "romkatv";
repo = "powerlevel10k";
rev = "v1.17.0";
sha256 = "sha256-fgrwbWj6CcPoZ6GbCZ47HRUg8ZSJWOsa7aipEqYuE0Q=";
};
file = "powerlevel10k.zsh-theme";
}
{
name = "powerlevel10k-config";
src = lib.cleanSource ./.;
file = "p10k.zsh";
}
{
name = "base16-shell";
src = fetchFromGitHub {
owner = "chriskempson";
repo = "base16-shell";
rev = "588691ba71b47e75793ed9edfcfaa058326a6f41";
sha256 = "sha256-X89FsG9QICDw3jZvOCB/KsPBVOLUeE7xN3VCtf0DD3E=";
};
file = "base16-shell.plugin.zsh";
}
];
};
};
};
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.user;
in {
options.aa.user = with types; {
name = mkOption {
type = str;
default = "alejandro";
description = "The name to use for the user account.";
};
fullName = mkOption {
type = str;
default = "Alejandro Angulo";
description = "The full name of the user.";
};
email = mkOption {
type = str;
default = "iam@alejandr0angul0.dev";
description = "The email of the user.";
};
extraGroups = mkOption {
type = listOf str;
default = ["video" "networkmanager"];
description = "Groups to for the user to be assigned.";
};
extraOptions = mkOption {
type = attrs;
default = {};
description = "Extra options passed to <option>users.users.<name></option>.";
};
};
config = {
# Required when setting shell to zsh
# There is a separate module that configures zsh for make
# Refer to modules/tools/zsh/default.nix
programs.zsh.enable = true;
users.users.${cfg.name} =
{
isNormalUser = true;
inherit (cfg) name;
home = "/home/${cfg.name}";
group = "users";
shell = pkgs.zsh;
extraGroups = ["wheel"] ++ cfg.extraGroups;
}
// cfg.extraOptions;
};
}