├── .gitignore
├── README.md
├── android.nix
├── audio.nix
├── base.nix
├── config
├── compton-inverted
├── compton-noninverted
├── dunstrc
├── i3
├── i3status
├── i3status-netns
├── init.el
└── xresources
├── copied
├── dhcpcd.nix
└── wpa_supplicant.nix
├── dev-tools.nix
├── entrypoints
├── gurney.nix
└── thufir.nix
├── fonts.nix
├── games.nix
├── gui-tools.nix
├── inl-tools.nix
├── laptop-base.nix
├── networking.nix
├── nix.nix
├── nixpkgs.nix
├── rust-overlay.nix
├── syncthing.nix
├── sysadmin.nix
├── uefi.nix
├── utility-scripts.nix
├── virtualization.nix
├── wireguard-client.nix
└── x.nix
/.gitignore:
--------------------------------------------------------------------------------
1 | default.nix
2 | private
3 | hardware-configuration.nix
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | nixos-configuration
2 | ===================
3 |
4 | This is a decently modularized set of configuration files for a NixOS
5 | system, which I mainly use to configure my laptop.
6 |
7 | The entrypoint is `default.nix`, and the module system is used
8 | heavily.
9 |
10 | Private files/data are placed in a `private` subdirectory, which is
11 | hidden via `.gitignore`.
12 |
13 | I place this repository in `/etc/nixos`, next to my local checkout of
14 | nixpkgs, which I use instead of the channel mechanism. A suitably
15 | modified `NIX_PATH` allows this to work (see `nix.nix`).
16 |
17 | ```bash
18 | [anders@gurney:/etc/nixos]
19 | $ ls -la
20 | total 16
21 | drwxr-xr-x 4 root root 4096 Mar 21 22:30 .
22 | drwxr-xr-x 23 root root 4096 Mar 21 22:31 ..
23 | drwxr-xr-x 6 anders users 4096 Mar 21 22:34 configuration
24 | drwxrwxr-x 9 anders users 4096 Mar 21 19:31 nixpkgs
25 | [anders@gurney:/etc/nixos]
26 | $ echo $NIX_PATH
27 | /etc/nixos:nixos-config=/etc/nixos/configuration
28 | ```
29 |
--------------------------------------------------------------------------------
/android.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { programs.adb = {
4 | enable = true;
5 | };
6 | }
7 |
--------------------------------------------------------------------------------
/audio.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | let pulse = pkgs.pulseaudioFull;
4 | in {
5 | boot = {
6 | kernelModules = [ "snd-seq" "snd-rawmidi" ];
7 | };
8 |
9 | hardware.pulseaudio = {
10 | enable = true;
11 | support32Bit = true;
12 | package = pulse;
13 | };
14 |
15 | services.mpd = {
16 | enable = true;
17 | user = "anders";
18 | group = "users";
19 | musicDirectory = "/home/anders/Music";
20 | dataDir = "/home/anders/.mpd";
21 | extraConfig = ''
22 | audio_output {
23 | type "pulse"
24 | name "Local MPD"
25 | server "127.0.0.1"
26 | }
27 | '';
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/base.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { boot = {
4 | cleanTmpDir = true;
5 | kernelPackages = pkgs.linuxPackages_latest;
6 | kernel.sysctl = {
7 | "net.ipv4.ip_forward" = 1;
8 | "vm.overcommit_memory" = 1;
9 | };
10 | kernelParams = [
11 | "transparent_hugepage=never"
12 | ];
13 | };
14 |
15 | documentation.man.enable = true;
16 |
17 | environment.variables = { EDITOR = "editor"; };
18 |
19 | networking = {
20 | firewall = {
21 | allowPing = true;
22 | };
23 | };
24 |
25 | programs = {
26 | bash = {
27 | interactiveShellInit = ''
28 | HISTCONTROL=ignoreboth:erasedups
29 | shopt -s histappend
30 | '';
31 | promptInit = ''
32 | PS1="\[\033[1;32m\][\u@\h:\w]\n\$\[\033[0m\] "
33 | '';
34 | shellAliases = { ssh = "TERM=xterm-256color ssh"; };
35 | };
36 | ssh.startAgent = false;
37 | };
38 |
39 | services = {
40 | openssh.enable = true;
41 | nixosManual.showManual = true;
42 | };
43 |
44 | security = {
45 | sudo.wheelNeedsPassword = false;
46 | pam.loginLimits =
47 | [ { domain = "*"; item = "nofile"; type = "-"; value = "999999"; }
48 | ];
49 | };
50 |
51 | time.timeZone = "America/Los_Angeles";
52 | }
53 |
--------------------------------------------------------------------------------
/config/compton-inverted:
--------------------------------------------------------------------------------
1 | backend = "glx"
2 | vsync = "opengl"
3 |
4 | opacity-rule = [
5 | "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
6 | ];
7 | inactive-opacity = 0.7
8 |
9 | invert-color-include = [ "class_g ~?= '(Okular|Evince|Pavucontrol|Chromium|libprs500|Conkeror|scide|Audacious|Firefox|Tomahawk|KeePassX|Quassel|Clementine)' && name !~?= 'Facebook|Youtube|YouTube - Vimperator$|Card Game|[.]elm - Nightly$|localhost|NOINVERT'" ];
--------------------------------------------------------------------------------
/config/compton-noninverted:
--------------------------------------------------------------------------------
1 | backend = "glx"
2 | vsync = "opengl"
3 |
4 | opacity-rule = [
5 | "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
6 | ];
7 | inactive-opacity = 0.7
8 |
--------------------------------------------------------------------------------
/config/dunstrc:
--------------------------------------------------------------------------------
1 | [global]
2 | font = Monospace 8
3 |
4 | # Allow a small subset of html markup:
5 | # bold
6 | # italic
7 | # strikethrough
8 | # underline
9 | #
10 | # For a complete reference see
11 | # .
12 | # If markup is not allowed, those tags will be stripped out of the
13 | # message.
14 | allow_markup = yes
15 |
16 | # The format of the message. Possible variables are:
17 | # %a appname
18 | # %s summary
19 | # %b body
20 | # %i iconname (including its path)
21 | # %I iconname (without its path)
22 | # %p progress value if set ([ 0%] to [100%]) or nothing
23 | # Markup is allowed
24 | format = "%s\n%b %p"
25 |
26 | # Sort messages by urgency.
27 | sort = yes
28 |
29 | # Show how many messages are currently hidden (because of geometry).
30 | indicate_hidden = yes
31 |
32 | # Alignment of message text.
33 | # Possible values are "left", "center" and "right".
34 | alignment = center
35 |
36 | # The frequency with wich text that is longer than the notification
37 | # window allows bounces back and forth.
38 | # This option conflicts with "word_wrap".
39 | # Set to 0 to disable.
40 | bounce_freq = 0
41 |
42 | # Show age of message if message is older than show_age_threshold
43 | # seconds.
44 | # Set to -1 to disable.
45 | show_age_threshold = 60
46 |
47 | # Split notifications into multiple lines if they don't fit into
48 | # geometry.
49 | word_wrap = yes
50 |
51 | # Ignore newlines '\n' in notifications.
52 | ignore_newline = no
53 |
54 |
55 | # The geometry of the window:
56 | # [{width}]x{height}[+/-{x}+/-{y}]
57 | # The geometry of the message window.
58 | # The height is measured in number of notifications everything else
59 | # in pixels. If the width is omitted but the height is given
60 | # ("-geometry x2"), the message window expands over the whole screen
61 | # (dmenu-like). If width is 0, the window expands to the longest
62 | # message displayed. A positive x is measured from the left, a
63 | # negative from the right side of the screen. Y is measured from
64 | # the top and down respectevly.
65 | # The width can be negative. In this case the actual width is the
66 | # screen width minus the width defined in within the geometry option.
67 | geometry = "300x5-30+20"
68 |
69 | # Shrink window if it's smaller than the width. Will be ignored if
70 | # width is 0.
71 | shrink = no
72 |
73 | # The transparency of the window. Range: [0; 100].
74 | # This option will only work if a compositing windowmanager is
75 | # present (e.g. xcompmgr, compiz, etc.).
76 | transparency = 0
77 |
78 | # Don't remove messages, if the user is idle (no mouse or keyboard input)
79 | # for longer than idle_threshold seconds.
80 | # Set to 0 to disable.
81 | idle_threshold = 120
82 |
83 | # Which monitor should the notifications be displayed on.
84 | monitor = 0
85 |
86 | # Display notification on focused monitor. Possible modes are:
87 | # mouse: follow mouse pointer
88 | # keyboard: follow window with keyboard focus
89 | # none: don't follow anything
90 | #
91 | # "keyboard" needs a windowmanager that exports the
92 | # _NET_ACTIVE_WINDOW property.
93 | # This should be the case for almost all modern windowmanagers.
94 | #
95 | # If this option is set to mouse or keyboard, the monitor option
96 | # will be ignored.
97 | follow = keyboard
98 |
99 | # Should a notification popped up from history be sticky or timeout
100 | # as if it would normally do.
101 | sticky_history = yes
102 |
103 | # Maximum amount of notifications kept in history
104 | history_length = 20
105 |
106 | # Display indicators for URLs (U) and actions (A).
107 | show_indicators = yes
108 |
109 | # The height of a single line. If the height is smaller than the
110 | # font height, it will get raised to the font height.
111 | # This adds empty space above and under the text.
112 | line_height = 0
113 |
114 | # Draw a line of "separatpr_height" pixel height between two
115 | # notifications.
116 | # Set to 0 to disable.
117 | separator_height = 2
118 |
119 | # Padding between text and separator.
120 | padding = 8
121 |
122 | # Horizontal padding.
123 | horizontal_padding = 8
124 |
125 | # Define a color for the separator.
126 | # possible values are:
127 | # * auto: dunst tries to find a color fitting to the background;
128 | # * foreground: use the same color as the foreground;
129 | # * frame: use the same color as the frame;
130 | # * anything else will be interpreted as a X color.
131 | separator_color = frame
132 |
133 | # Print a notification on startup.
134 | # This is mainly for error detection, since dbus (re-)starts dunst
135 | # automatically after a crash.
136 | startup_notification = false
137 |
138 | # dmenu path.
139 | dmenu = dmenu -p dunst:
140 |
141 | # Browser for opening urls in context menu.
142 | browser = browser
143 |
144 | # Align icons left/right/off
145 | icon_position = left
146 |
147 | # Paths to default icons.
148 | # icon_folders = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/
149 |
150 | [frame]
151 | width = 3
152 | color = "#aaaaaa"
153 |
154 | [shortcuts]
155 |
156 | # Shortcuts are specified as [modifier+][modifier+]...key
157 | # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2",
158 | # "mod3" and "mod4" (windows-key).
159 | # Xev might be helpful to find names for keys.
160 |
161 | # Close notification.
162 | close = mod4+space
163 |
164 | # Close all notifications.
165 | # close_all = mod4+shift+space
166 |
167 | # Redisplay last message(s).
168 | # On the US keyboard layout "grave" is normally above TAB and left
169 | # of "1".
170 | history = mod4+shift+space
171 |
172 | # Context menu.
173 | # context = ctrl+shift+period
174 |
175 | [urgency_low]
176 | # IMPORTANT: colors have to be defined in quotation marks.
177 | # Otherwise the "#" and following would be interpreted as a comment.
178 | background = "#222222"
179 | foreground = "#888888"
180 | timeout = 10
181 |
182 | [urgency_normal]
183 | background = "#285577"
184 | foreground = "#ffffff"
185 | timeout = 10
186 |
187 | [urgency_critical]
188 | background = "#900000"
189 | foreground = "#ffffff"
190 | timeout = 0
191 |
192 |
193 | # Every section that isn't one of the above is interpreted as a rules to
194 | # override settings for certain messages.
195 | # Messages can be matched by "appname", "summary", "body", "icon", "category",
196 | # "msg_urgency" and you can override the "timeout", "urgency", "foreground",
197 | # "background", "new_icon" and "format".
198 | # Shell-like globbing will get expanded.
199 | #
200 | # SCRIPTING
201 | # You can specify a script that gets run when the rule matches by
202 | # setting the "script" option.
203 | # The script will be called as follows:
204 | # script appname summary body icon urgency
205 | # where urgency can be "LOW", "NORMAL" or "CRITICAL".
206 | #
207 | # NOTE: if you don't want a notification to be displayed, set the format
208 | # to "".
209 | # NOTE: It might be helpful to run dunst -print in a terminal in order
210 | # to find fitting options for rules.
211 |
212 | #[espeak]
213 | # summary = "*"
214 | # script = dunst_espeak.sh
215 |
216 | #[script-test]
217 | # summary = "*script*"
218 | # script = dunst_test.sh
219 |
220 | #[ignore]
221 | # # This notification will not be displayed
222 | # summary = "foobar"
223 | # format = ""
224 |
225 | #[signed_on]
226 | # appname = Pidgin
227 | # summary = "*signed on*"
228 | # urgency = low
229 | #
230 | #[signed_off]
231 | # appname = Pidgin
232 | # summary = *signed off*
233 | # urgency = low
234 | #
235 | #[says]
236 | # appname = Pidgin
237 | # summary = *says*
238 | # urgency = critical
239 | #
240 | #[twitter]
241 | # appname = Pidgin
242 | # summary = *twitter.com*
243 | # urgency = normal
244 | #
245 | # vim: ft=cfg
246 |
--------------------------------------------------------------------------------
/config/i3:
--------------------------------------------------------------------------------
1 | ##########
2 | # Behavior
3 | ##########
4 |
5 | workspace_layout tabbed
6 |
7 | no_focus [class="Chromium"]
8 | no_focus [class="Firefox"]
9 | focus_on_window_activation focus
10 |
11 | for_window [title="Org Select"] floating enable
12 | for_window [title="CAPTURE"] floating enable
13 |
14 | new_window none
15 | hide_edge_borders both
16 | force_focus_wrapping yes
17 |
18 | gaps inner 6
19 | gaps outer 6
20 | smart_gaps on
21 |
22 | #############
23 | # Keybindings
24 | #############
25 |
26 | set $mod Mod4
27 |
28 | bindsym $mod+Shift+Return exec anders-terminal
29 | bindsym $mod+Return exec alacritty
30 |
31 | bindsym $mod+d exec rofi -show run
32 |
33 | bindsym F1 exec anders-handle-keybind F1
34 | bindsym F2 exec anders-handle-keybind F2
35 | bindsym F3 exec anders-handle-keybind F3
36 | bindsym F7 exec anders-handle-keybind F7
37 | bindsym F9 exec anders-handle-keybind F9
38 | bindsym F10 exec anders-handle-keybind F10
39 | bindsym F11 exec anders-handle-keybind F11
40 | bindsym F12 exec anders-handle-keybind F12
41 |
42 | bindsym $mod+Shift+q kill
43 |
44 | bindsym $mod+comma workspace prev
45 | bindsym $mod+period workspace next
46 |
47 | bindsym $mod+j exec i3-focus down
48 | bindsym $mod+k exec i3-focus up
49 | bindsym $mod+h exec i3-focus left
50 | bindsym $mod+l exec i3-focus right
51 |
52 | bindsym $mod+Tab focus right
53 | bindsym $mod+grave focus left
54 |
55 |
56 | bindsym $mod+Shift+j move down
57 | bindsym $mod+Shift+k move up
58 | bindsym $mod+Shift+h move left
59 | bindsym $mod+Shift+l move right
60 |
61 | bindsym $mod+s split h
62 | bindsym $mod+v split v
63 |
64 | bindsym $mod+p focus parent
65 | bindsym $mod+c focus child
66 |
67 | # switch to workspace
68 | bindsym $mod+1 workspace 1
69 | bindsym $mod+2 workspace 2
70 | bindsym $mod+3 workspace 3
71 | bindsym $mod+4 workspace 4
72 | bindsym $mod+5 workspace 5
73 | bindsym $mod+6 workspace 6
74 | bindsym $mod+7 workspace 7
75 | bindsym $mod+8 workspace 8
76 | bindsym $mod+9 workspace 9
77 | bindsym $mod+0 workspace 10
78 |
79 | # move focused container to workspace
80 | bindsym $mod+Shift+1 move container to workspace 1
81 | bindsym $mod+Shift+2 move container to workspace 2
82 | bindsym $mod+Shift+3 move container to workspace 3
83 | bindsym $mod+Shift+4 move container to workspace 4
84 | bindsym $mod+Shift+5 move container to workspace 5
85 | bindsym $mod+Shift+6 move container to workspace 6
86 | bindsym $mod+Shift+7 move container to workspace 7
87 | bindsym $mod+Shift+8 move container to workspace 8
88 | bindsym $mod+Shift+9 move container to workspace 9
89 | bindsym $mod+Shift+0 move container to workspace 10
90 |
91 | #######
92 | # Looks
93 | #######
94 |
95 | # Font for window titles. Will also be used by the bar unless a different font
96 | # is used in the bar {} block below.
97 | # This font is widely installed, provides lots of unicode glyphs, right-to-left
98 | # text rendering and scalability on retina/hidpi displays (thanks to pango).
99 | font pango:DejaVu Sans Mono 11
100 |
101 | # Start i3bar to display a workspace bar (plus the system information i3status
102 | # finds out, if available)
103 | bar {
104 | status_command anders-i3status
105 |
106 | colors {
107 | background $bg
108 | statusline $fg
109 | separator $hi
110 | focused_workspace $gn $bg $ac
111 | active_workspace $gn $ac $tx
112 | inactive_workspace $bg $bg $ia
113 | urgent_workspace $rd $bg $ac
114 | }
115 | }
116 |
117 | # color defines for zenburn styled i3
118 | set $bg #2c2c2e
119 | set $fg #9f9f9f
120 | set $hi #efef8f
121 | set $ac #a0afa0
122 | set $tx #040404
123 | set $ia #8f8f8f
124 | set $be #8faf9f
125 | set $yw #ccdc90
126 | set $gn #88b090
127 | set $rd #e89393
128 |
129 | # set some nice colors border background text
130 | client.focused $bg $rd $tx
131 | client.focused_inactive $bg $yw $tx
132 | client.unfocused $bg $ac $tx
133 | client.urgent $bg $bg $ac
134 | # client.unfocused $bg $bg $ia
135 | # client.focused_inactive $bg $bg $ac
136 | # client.urgent $rd $rd $tx
137 |
--------------------------------------------------------------------------------
/config/i3status:
--------------------------------------------------------------------------------
1 | general {
2 | output_format = i3bar
3 | colors = true
4 | interval = 1
5 | }
6 |
7 | order += "wireless wlp4s0"
8 | order += "volume pulse"
9 | order += "battery 0"
10 | order += "tztime local"
11 |
12 | wireless wlp4s0 {
13 | format_up = "W: (%quality at %essid) %ip"
14 | format_down = "W: down"
15 | }
16 |
17 | volume pulse {
18 | format = "♪: %volume"
19 | format_muted = "♪: muted (%volume)"
20 | device = "pulse"
21 | }
22 |
23 | disk "/" {
24 | format = "/ %avail"
25 | }
26 |
27 | disk "/nix/store" {
28 | format = "/nix/store %avail"
29 | }
30 |
31 | disk "/home" {
32 | format = "/home %avail"
33 | }
34 |
35 | battery 0 {
36 | format = "%status %percentage %remaining"
37 | last_full_capacity = true
38 | integer_battery_capacity = true
39 | low_threshold = 15
40 | threshold_type = percentage
41 | }
42 |
43 | tztime local {
44 | format = "%Y-%m-%d %H:%M:%S"
45 | }
46 |
--------------------------------------------------------------------------------
/config/i3status-netns:
--------------------------------------------------------------------------------
1 | general {
2 | output_format = i3bar
3 | colors = true
4 | interval = 1
5 | }
6 |
7 | order += "wireless wlp4s0"
8 |
9 | wireless wlp4s0 {
10 | format_up = "W: (%quality at %essid) %ip"
11 | format_down = "W: down"
12 | }
13 |
--------------------------------------------------------------------------------
/config/init.el:
--------------------------------------------------------------------------------
1 | ;;; bootstrap use-package
2 |
3 | (require 'package)
4 | (setq package-enable-at-startup nil)
5 | (add-to-list 'package-archives
6 | '("melpa-stable" . "https://stable.melpa.org/packages/") t)
7 | (add-to-list 'package-archives '("orgmode" . "http://orgmode.org/elpa/"))
8 | (package-initialize)
9 |
10 | (unless (package-installed-p 'use-package)
11 | (package-refresh-contents)
12 | (package-install 'use-package))
13 | (require 'use-package)
14 | (setq use-package-always-ensure t)
15 |
16 | ;;; Elisp utilities
17 |
18 | (use-package f)
19 | (use-package s)
20 |
21 | ;;; Actual packages, except language-specific
22 |
23 | (use-package avy
24 | :bind ("C-t" . avy-goto-char))
25 |
26 | (use-package company
27 | :bind (:map company-active-map
28 | ("RET" . nil)
29 | ("M-1" . company-complete-selection))
30 | :init
31 | (setq company-global-modes '(not gud-mode))
32 | (setq company-dabbrev-downcase nil)
33 | :config
34 | (global-company-mode))
35 |
36 | (use-package compile
37 | :init
38 | (setq compilation-always-kill t)
39 | (setq compilation-ask-about-save nil)
40 | :config
41 | ;; Do to my particular windowing setup (only window-manager-level
42 | ;; splits), I want a drastically simpler version of
43 | ;; compilation-goto-locus. It's not really possible to do this from
44 | ;; the outside, so just override the function.
45 | (defun compilation-goto-locus (msg mk end-mk)
46 | "Jump to an error corresponding to MSG at MK.
47 | All arguments are markers. If END-MK is non-nil, mark is set there
48 | and overlay is highlighted between MK and END-MK."
49 |
50 | (display-buffer (marker-buffer msg) '(nil (allow-no-window . t)))
51 | (with-current-buffer (marker-buffer msg)
52 | (goto-char (marker-position msg))
53 | (and w (compilation-set-window w msg)))
54 |
55 | (display-buffer (marker-buffer mk))
56 |
57 | (with-current-buffer (marker-buffer mk)
58 | (unless (eq (goto-char mk) (point))
59 | ;; If narrowing gets in the way of going to the right place, widen.
60 | (widen)
61 | (if next-error-move-function
62 | (funcall next-error-move-function msg mk)
63 | (goto-char mk)))
64 | (if end-mk
65 | (push-mark end-mk t)
66 | (if mark-active (setq mark-active)))
67 | ;; If hideshow got in the way of
68 | ;; seeing the right place, open permanently.
69 | (dolist (ov (overlays-at (point)))
70 | (when (eq 'hs (overlay-get ov 'invisible))
71 | (delete-overlay ov)
72 | (goto-char mk))))))
73 |
74 | (use-package expand-region
75 | :bind ("C-=" . er/expand-region))
76 |
77 | (use-package flymake)
78 |
79 | (use-package god-mode
80 | :bind (("" . god-local-mode)
81 | :map god-local-mode-map
82 | ("i" . god-local-mode)
83 | ("." . repeat)
84 | :map isearch-mode-map
85 | ("" . god-mode-isearch-activate)
86 | :map god-mode-isearch-map
87 | ("" . god-mode-isearch-disable))
88 | :init
89 | (setq god-mod-alist
90 | '((nil . "C-")
91 | ("t" . "M-")
92 | ("T" . "C-M-")))
93 | (defun anders/update-cursor ()
94 | (setq cursor-type (if god-local-mode 'box 'bar)))
95 | :hook
96 | ((god-mode-enabled god-mode-disabled) . anders/update-cursor)
97 | :config
98 | (require 'god-mode-isearch)
99 |
100 | ;; bugfix for https://github.com/chrisdone/god-mode/issues/110
101 | (defun god-mode-upper-p (char)
102 | "Is the given char upper case?"
103 | (and (>= char ?A)
104 | (<= char ?Z)
105 | (/= char ?T))))
106 |
107 | (use-package ivy
108 | :init
109 | (setq ivy-initial-inputs-alist '())
110 | :config
111 | (ivy-mode 0))
112 |
113 | ;; Magit is awesome.
114 | (use-package magit
115 | :init
116 | (setq magit-commit-show-diff nil)
117 | (setq magit-delete-by-moving-to-trash nil)
118 | (setq magit-diff-expansion-threshold 2.0)
119 | (setq magit-diff-use-overlays nil)
120 | (setq magit-no-confirm
121 | '(abort-rebase
122 | delete-unmerged-branch
123 | drop-stashes
124 | stage-all-changes
125 | unstage-all-changes))
126 | (setq magit-revert-buffers t)
127 | (setq magit-use-overlays nil))
128 |
129 | (use-package man
130 | :init
131 | (setq Man-width 80)
132 | (setq Man-notify-method 'pushy))
133 |
134 | (use-package multiple-cursors
135 | :bind (("C-S-c C-S-c" . mc/edit-lines)
136 | ("C->" . mc/mark-next-like-this)
137 | ("C-<" . mc/mark-previous-like-this)
138 | ("C-c C-<" . mc/mark-all-like-this)))
139 |
140 | (use-package org
141 | :bind (("C-c a" . org-agenda))
142 | :hook
143 | ((org-mode) . real-auto-save-mode)
144 | ((org-mode) . auto-revert-mode)
145 | ((org-capture-after-finalize) . delete-frame)
146 | :init
147 | ;; Utility function so that I don't have to fix the set of org files
148 | ;; statically.
149 | (defun anders/dynamic-org-files (directory)
150 | (f-entries directory
151 | (lambda (filename) (s-ends-with-p ".org" filename))
152 | t))
153 | (defun anders/dynamic-all-org-files ()
154 | (anders/dynamic-org-files "~/projects"))
155 |
156 | (setq org-agenda-window-setup 'current-window)
157 |
158 | ;; Set up the agenda for the particular things I want out of it.
159 | (setq org-agenda-compact-blocks t)
160 | (setq org-agenda-span 'day)
161 | (setq org-agenda-time-grid
162 | '((daily today require-timed)
163 | ()
164 | "......"))
165 | (setq org-agenda-custom-commands
166 | '(("a" "Agenda"
167 | ((agenda ""
168 | ((org-agenda-files
169 | (anders/dynamic-org-files "~/projects"))
170 | (org-super-agenda-groups
171 | '((:discard (:tag "agenda_ignore"))
172 | (:name "Important"
173 | :priority "A")
174 | (:name "Appointments"
175 | :time-grid t)
176 | (:name "Tasks"
177 | :scheduled t)
178 | ))))
179 | (tags-todo "+project+active"
180 | ((org-agenda-files
181 | (anders/dynamic-org-files "~/projects"))))
182 | (tags "+project+ongoing"
183 | ((org-agenda-files
184 | (anders/dynamic-org-files "~/projects"))
185 | (org-use-tag-inheritance nil)))))
186 | ("c" "Captures"
187 | ((tags-todo "capture"
188 | ((org-agenda-files
189 | (anders/dynamic-org-files "~/projects/special"))
190 | (org-use-tag-inheritance t)
191 | (org-agenda-overriding-header "Capture")))))))
192 |
193 | (setq org-capture-templates
194 | '(("t" "Todo" entry
195 | (file "~/projects/special/capture/capture.org")
196 | "* TODO %?\n %i")))
197 |
198 | (setq org-goto-interface 'outline-path-completion)
199 |
200 | ;; I only refile from my capture files to the top (file) level of
201 | ;; other org files.
202 | ;;
203 | ;; Forcing level == 100 is a hack to perfomantly filter out all
204 | ;; headings and leave only file names.
205 | ;;
206 | ;; The argument to org-refile-targets must be a named function.
207 | (setq org-refile-use-outline-path 't)
208 | (setq org-refile-targets '((anders/dynamic-all-org-files . (:tag . "refile"))))
209 | (setq org-outline-path-complete-in-steps nil)
210 |
211 | ;; Miscellaneous
212 | (setq org-fast-tag-selection-single-key t)
213 | (setq org-from-is-user-regexp nil)
214 | (setq org-hide-leading-stars t)
215 | (setq org-read-date-force-compatible-dates nil)
216 | (setq org-read-date-popup-calendar nil))
217 |
218 | (use-package org-super-agenda
219 | :config
220 | (org-super-agenda-mode))
221 |
222 | (use-package projectile
223 | :init
224 | (defun anders/vc-or-dired ()
225 | (interactive)
226 | (projectile-dired)
227 | (ignore-errors (projectile-vc)))
228 | (defun anders/ignore-project (project)
229 | (string-match-p "/nix/store" project))
230 | (setq projectile-keymap-prefix (kbd "M-t"))
231 | (setq projectile-mode-line
232 | ''(:eval (format "Projectile[%s]" default-directory)))
233 | (setq projectile-switch-project-action 'anders/vc-or-dired)
234 | (setq projectile-completion-system 'ivy)
235 | (setq projectile-ignored-project-function 'anders/ignore-project)
236 | :config
237 | (projectile-global-mode)
238 | (ad-deactivate 'compilation-find-file))
239 |
240 | (use-package projectile-ripgrep
241 | :bind ((:map projectile-command-map
242 | (("s g" . projectile-ripgrep)))))
243 |
244 | (use-package real-auto-save
245 | :init
246 | (setq real-auto-save-interval 30))
247 |
248 | (use-package subword
249 | :config
250 | (global-subword-mode))
251 |
252 | (use-package term
253 | :bind (("M-RET" . anders/get-term)
254 | :map term-mode-map
255 | (("M-i" . anders/term-toggle-mode))
256 | :map term-raw-map
257 | (("M-i" . anders/term-toggle-mode)
258 | ("C-y" . term-paste)))
259 | :init
260 | (defun anders/new-term ()
261 | (interactive)
262 | (term "bash")
263 | (rename-buffer "shell" t))
264 | (defun anders/get-term ()
265 | (interactive)
266 | (if (get-buffer "shell")
267 | (switch-to-buffer "shell")
268 | (anders/new-term)))
269 | (defun anders/expose-global-binding-in-term (binding)
270 | (define-key term-raw-map binding
271 | (lookup-key (current-global-map) binding)))
272 | (defun anders/term-toggle-mode ()
273 | "Toggles term between line mode and char mode"
274 | (interactive)
275 | (if (term-in-line-mode)
276 | (term-char-mode)
277 | (term-line-mode)))
278 | :config
279 | (anders/expose-global-binding-in-term (kbd "M-x"))
280 | (anders/expose-global-binding-in-term (kbd "C-x"))
281 | (anders/expose-global-binding-in-term (kbd "C-c a")))
282 |
283 |
284 | (use-package tramp
285 | :init
286 | (setq tramp-default-method "ssh")
287 | (setq tramp-use-ssh-controlmaster-options nil)
288 | :config
289 | (add-to-list 'tramp-remote-path "/run/current-system/sw/bin"))
290 |
291 | (use-package undo-tree
292 | :init
293 | (setq undo-tree-auto-save-history t)
294 | (setq undo-tree-history-directory-alist '(("." . "/tmp/undo-tree")))
295 | :config
296 | (global-undo-tree-mode))
297 |
298 | (use-package whitespace
299 | :bind ("C-x C-s" . anders/save-with-delete-trailing-whitespace)
300 | :hook ((prog-mode . whitespace-mode))
301 | :init
302 | (setq-default indent-tabs-mode nil)
303 | (setq whitespace-style '(face tabs))
304 | (defun anders/save-with-delete-trailing-whitespace ()
305 | (interactive)
306 | (delete-trailing-whitespace)
307 | (save-buffer)))
308 |
309 | ;;; Programming-language specific packages
310 |
311 | (use-package cargo)
312 |
313 | (use-package elm-mode
314 | :init
315 | (setq elm-sort-imports-on-save t)
316 | (setq elm-format-on-save t))
317 |
318 | (use-package haskell-mode)
319 |
320 | (use-package intero
321 | :init
322 | (defun anders/intero-mode-unless-global-project ()
323 | "Run intero-mode iff we're in a project with a stack.yaml"
324 | (interactive)
325 | (let* ((stack-command "stack path --project-root --verbosity silent")
326 | (stack-path (ignore-errors (shell-command-to-string stack-command))))
327 | (unless (or
328 | (string-match-p (regexp-quote "not found") stack-path)
329 | (string-match-p (regexp-quote "global") stack-path))
330 | (intero-mode))))
331 | :hook ((haskell-mode . anders/intero-mode-unless-global-project)))
332 | (setq haskell-mode-hook nil)
333 |
334 | (use-package lua-mode)
335 |
336 | (use-package markdown-mode
337 | :mode
338 | (("\\.markdown\\'" . markdown-mode)
339 | ("\\.md\\'" . markdown-mode)))
340 |
341 | (use-package nix-mode)
342 |
343 | (use-package protobuf-mode)
344 |
345 | (use-package rust-mode
346 | :init
347 | (eval-after-load 'compile
348 | (remove-hook 'next-error-hook 'rustc-scroll-down-after-next-error)))
349 |
350 | (use-package yaml-mode)
351 |
352 | ;;; Copy/paste
353 |
354 | (setq kill-do-not-save-duplicates t)
355 | (setq save-interprogram-paste-before-kill t)
356 | (setq select-enable-clipboard nil)
357 | (setq select-enable-primary t)
358 |
359 | ;;; Window management
360 |
361 | ;; gud mode is a bad actor
362 | (setq gdb-display-io-nopopup t)
363 |
364 | (setq frame-auto-hide-function 'delete-frame)
365 | (setq display-buffer-alist
366 | '(("shell.*" (display-buffer-same-window) ())
367 | (".*" (display-buffer-reuse-window
368 | display-buffer-same-window
369 | display-buffer-pop-up-frame)
370 | (reusable-frames . t))))
371 |
372 | (defun anders/same-window-instead
373 | (orig-fun buffer alist)
374 | (display-buffer-same-window buffer nil))
375 | (advice-add 'display-buffer-pop-up-window :around 'anders/same-window-instead)
376 |
377 | (defun anders/do-select-frame (orig-fun buffer &rest args)
378 | (let* ((old-frame (selected-frame))
379 | (window (apply orig-fun buffer args))
380 | (frame (window-frame window)))
381 | (unless (eq frame old-frame)
382 | (select-frame-set-input-focus frame))
383 | (select-window window)
384 | window))
385 | (advice-add 'display-buffer :around 'anders/do-select-frame)
386 |
387 | ;; Dedicated windows are evil
388 | (advice-add 'set-window-dedicated-p :around
389 | (lambda (orig-fun &rest args) nil))
390 |
391 | ;;; Luddite mode
392 |
393 | (set-scroll-bar-mode nil)
394 | (setq tool-bar-mode nil)
395 | (setq menu-bar-mode nil)
396 | (setq initial-scratch-message nil)
397 |
398 | ;;; Looks
399 |
400 | (setq-default truncate-lines t)
401 | (set-face-attribute 'default nil :height 110)
402 | (set-face-attribute 'default nil :family "Inconsolata")
403 | ;; (load-theme 'deeper-blue)
404 | (show-paren-mode 1)
405 |
406 | ;;; Miscellaneous
407 |
408 | (defun anders/switch-to-previous-buffer ()
409 | "Switch to previously open buffer.
410 | Repeated invocations toggle between the two most recently open buffers."
411 | (interactive)
412 | (switch-to-buffer (other-buffer (current-buffer) 1)))
413 | (global-set-key "\M-o" 'anders/switch-to-previous-buffer)
414 |
415 | (global-set-key (kbd "C-z") nil)
416 | (global-set-key (kbd "C-x k") 'kill-this-buffer)
417 | (setq auto-save-file-name-transforms '((".*" "/tmp/" t)))
418 | (setq backup-directory-alist '((".*" . "/tmp/")))
419 | (setq dired-auto-revert-buffer t)
420 | (setq recenter-positions '(bottom middle top))
421 | (setq uniquify-buffer-name-style 'post-forward)
422 |
423 | ;;; various stuff that I just always want to have open
424 |
425 | (when (daemonp)
426 | (progn
427 | (find-file-noselect "/etc/nixos/configuration/config/init.el")
428 | (find-file-noselect "/etc/nixos/configuration/private/bad-hosts.nix")
429 | (man "configuration.nix")))
430 |
--------------------------------------------------------------------------------
/config/xresources:
--------------------------------------------------------------------------------
1 | # ! Solarized color scheme for the X Window System
2 | # !
3 | # ! http://ethanschoonover.com/solarized
4 | #
5 | #
6 | # ! Common
7 | #
8 | # #define S_yellow #b58900
9 | # #define S_orange #cb4b16
10 | # #define S_red #dc322f
11 | # #define S_magenta #d33682
12 | # #define S_violet #6c71c4
13 | # #define S_blue #268bd2
14 | # #define S_cyan #2aa198
15 | # #define S_green #859900
16 | #
17 | #
18 | # ! Dark
19 | #
20 | # ! #define S_base03 #002b36
21 | # ! #define S_base02 #073642
22 | # ! #define S_base01 #586e75
23 | # ! #define S_base00 #657b83
24 | # ! #define S_base0 #839496
25 | # ! #define S_base1 #93a1a1
26 | # ! #define S_base2 #eee8d5
27 | # ! #define S_base3 #fdf6e3
28 | #
29 | #
30 | # ! Light
31 | #
32 | # #define S_base03 #fdf6e3
33 | # #define S_base02 #eee8d5
34 | # #define S_base01 #93a1a1
35 | # #define S_base00 #839496
36 | # #define S_base0 #657b83
37 | # #define S_base1 #586e75
38 | # #define S_base2 #073642
39 | # #define S_base3 #002b36
40 | #
41 | #
42 | # *background: S_base03
43 | # *foreground: S_base0
44 | # *cursorColor: S_base1
45 | # *pointerColorBackground: S_base01
46 | # *pointerColorForeground: S_base1
47 | #
48 | # *color0: S_base02
49 | # *color1: S_red
50 | # *color2: S_green
51 | # *color3: S_yellow
52 | # *color4: S_blue
53 | # *color5: S_magenta
54 | # *color6: S_cyan
55 | # *color7: S_base2
56 | # *color9: S_orange
57 | # *color8: S_base03
58 | # *color10: S_base01
59 | # *color11: S_base00
60 | # *color12: S_base0
61 | # *color13: S_violet
62 | # *color14: S_base1
63 | # *color15: S_base3
64 |
--------------------------------------------------------------------------------
/copied/dhcpcd.nix:
--------------------------------------------------------------------------------
1 | { config, lib, pkgs, ... }:
2 |
3 | with lib;
4 |
5 | let
6 |
7 | dhcpcd = if !config.boot.isContainer then pkgs.dhcpcd else pkgs.dhcpcd.override { udev = null; };
8 |
9 | cfg = config.networking.dhcpcd;
10 |
11 | interfaces = attrValues config.networking.interfaces;
12 |
13 | enableDHCP = config.networking.dhcpcd.enable &&
14 | (config.networking.useDHCP || any (i: i.useDHCP == true) interfaces);
15 |
16 | # Don't start dhcpcd on explicitly configured interfaces or on
17 | # interfaces that are part of a bridge, bond or sit device.
18 | ignoredInterfaces =
19 | map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ipv4.addresses != [ ]) interfaces)
20 | ++ mapAttrsToList (i: _: i) config.networking.sits
21 | ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
22 | ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
23 | ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
24 | ++ config.networking.dhcpcd.denyInterfaces;
25 |
26 | arrayAppendOrNull = a1: a2: if a1 == null && a2 == null then null
27 | else if a1 == null then a2 else if a2 == null then a1
28 | else a1 ++ a2;
29 |
30 | # If dhcp is disabled but explicit interfaces are enabled,
31 | # we need to provide dhcp just for those interfaces.
32 | allowInterfaces = arrayAppendOrNull cfg.allowInterfaces
33 | (if !config.networking.useDHCP && enableDHCP then
34 | map (i: i.name) (filter (i: i.useDHCP == true) interfaces) else null);
35 |
36 | # Config file adapted from the one that ships with dhcpcd.
37 | dhcpcdConf = pkgs.writeText "dhcpcd.conf"
38 | ''
39 | # Inform the DHCP server of our hostname for DDNS.
40 | hostname
41 |
42 | # A list of options to request from the DHCP server.
43 | option domain_name_servers, domain_name, domain_search, host_name
44 | option classless_static_routes, ntp_servers, interface_mtu
45 |
46 | # A ServerID is required by RFC2131.
47 | # Commented out because of many non-compliant DHCP servers in the wild :(
48 | #require dhcp_server_identifier
49 |
50 | # A hook script is provided to lookup the hostname if not set by
51 | # the DHCP server, but it should not be run by default.
52 | nohook lookup-hostname
53 |
54 | # Ignore peth* devices; on Xen, they're renamed physical
55 | # Ethernet cards used for bridging. Likewise for vif* and tap*
56 | # (Xen) and virbr* and vnet* (libvirt).
57 | denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* sit*
58 |
59 | # Use the list of allowed interfaces if specified
60 | ${optionalString (allowInterfaces != null) "allowinterfaces ${toString allowInterfaces}"}
61 |
62 | ${cfg.extraConfig}
63 | '';
64 |
65 | exitHook = pkgs.writeText "dhcpcd.exit-hook"
66 | ''
67 | if [ "$reason" = BOUND -o "$reason" = REBOOT ]; then
68 | # Restart ntpd. We need to restart it to make sure that it
69 | # will actually do something: if ntpd cannot resolve the
70 | # server hostnames in its config file, then it will never do
71 | # anything ever again ("couldn't resolve ..., giving up on
72 | # it"), so we silently lose time synchronisation. This also
73 | # applies to openntpd.
74 | ${config.systemd.package}/bin/systemctl try-reload-or-restart ntpd.service openntpd.service || true
75 | fi
76 |
77 | ${cfg.runHook}
78 | '';
79 |
80 | in
81 |
82 | {
83 |
84 | ###### interface
85 |
86 | options = {
87 |
88 | networking.dhcpcd.enable = mkOption {
89 | type = types.bool;
90 | default = true;
91 | description = ''
92 | Whether to enable dhcpcd for device configuration. This is mainly to
93 | explicitly disable dhcpcd (for example when using networkd).
94 | '';
95 | };
96 |
97 | networking.dhcpcd.persistent = mkOption {
98 | type = types.bool;
99 | default = false;
100 | description = ''
101 | Whenever to leave interfaces configured on dhcpcd daemon
102 | shutdown. Set to true if you have your root or store mounted
103 | over the network or this machine accepts SSH connections
104 | through DHCP interfaces and clients should be notified when
105 | it shuts down.
106 | '';
107 | };
108 |
109 | networking.dhcpcd.denyInterfaces = mkOption {
110 | type = types.listOf types.str;
111 | default = [];
112 | description = ''
113 | Disable the DHCP client for any interface whose name matches
114 | any of the shell glob patterns in this list. The purpose of
115 | this option is to blacklist virtual interfaces such as those
116 | created by Xen, libvirt, LXC, etc.
117 | '';
118 | };
119 |
120 | networking.dhcpcd.allowInterfaces = mkOption {
121 | type = types.nullOr (types.listOf types.str);
122 | default = null;
123 | description = ''
124 | Enable the DHCP client for any interface whose name matches
125 | any of the shell glob patterns in this list. Any interface not
126 | explicitly matched by this pattern will be denied. This pattern only
127 | applies when non-null.
128 | '';
129 | };
130 |
131 | networking.dhcpcd.extraConfig = mkOption {
132 | type = types.lines;
133 | default = "";
134 | description = ''
135 | Literal string to append to the config file generated for dhcpcd.
136 | '';
137 | };
138 |
139 | networking.dhcpcd.runHook = mkOption {
140 | type = types.lines;
141 | default = "";
142 | example = "if [[ $reason =~ BOUND ]]; then echo $interface: Routers are $new_routers - were $old_routers; fi";
143 | description = ''
144 | Shell code that will be run after all other hooks. See
145 | `man dhcpcd-run-hooks` for details on what is possible.
146 | '';
147 | };
148 |
149 | };
150 |
151 |
152 | ###### implementation
153 |
154 | config = mkIf enableDHCP {
155 |
156 | systemd.services.dhcpcd = let
157 | cfgN = config.networking;
158 | hasDefaultGatewaySet = (cfgN.defaultGateway != null && cfgN.defaultGateway.address != "")
159 | && (!cfgN.enableIPv6 || (cfgN.defaultGateway6 != null && cfgN.defaultGateway6.address != ""));
160 | in
161 | { description = "DHCP Client";
162 |
163 | wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target";
164 | wants = [ "network.target" "systemd-udev-settle.service" ];
165 | before = [ "network.target" ];
166 | after = [ "systemd-udev-settle.service" ];
167 |
168 | # Stopping dhcpcd during a reconfiguration is undesirable
169 | # because it brings down the network interfaces configured by
170 | # dhcpcd. So do a "systemctl restart" instead.
171 | stopIfChanged = false;
172 |
173 | path = [ dhcpcd pkgs.nettools pkgs.openresolv ];
174 |
175 | unitConfig.ConditionCapability = "CAP_NET_ADMIN";
176 |
177 | serviceConfig = let
178 | phys-aware = pkgs.writeScript "phys-aware" ''
179 | #! ${pkgs.bash}/bin/bash
180 | if ${pkgs.iproute}/bin/ip link | ${pkgs.gnugrep}/bin/grep -q wgvpn0;
181 | then exec ${pkgs.iproute}/bin/ip netns exec physical "$@"
182 | else exec "$@"
183 | fi
184 | '';
185 | in { Type = "forking";
186 | PIDFile = "/run/dhcpcd.pid";
187 | ExecStart = "@${phys-aware} dhcpcd ${dhcpcd}/sbin/dhcpcd -w --quiet ${optionalString cfg.persistent "--persistent"} --config ${dhcpcdConf} ${concatStringsSep " " config.networking.wireless.interfaces}";
188 | ExecReload = "${dhcpcd}/sbin/dhcpcd --rebind";
189 | Restart = "always";
190 | };
191 | };
192 |
193 | environment.systemPackages = [ dhcpcd ];
194 |
195 | environment.etc =
196 | [ { source = exitHook;
197 | target = "dhcpcd.exit-hook";
198 | }
199 | ];
200 |
201 | powerManagement.resumeCommands = mkIf config.systemd.services.dhcpcd.enable
202 | ''
203 | # Tell dhcpcd to rebind its interfaces if it's running.
204 | ${config.systemd.package}/bin/systemctl reload dhcpcd.service
205 | '';
206 |
207 | };
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/copied/wpa_supplicant.nix:
--------------------------------------------------------------------------------
1 | { config, lib, pkgs, ... }:
2 |
3 | with lib;
4 |
5 | let
6 | cfg = config.networking.wireless;
7 | configFile = if cfg.networks != {} then pkgs.writeText "wpa_supplicant.conf" ''
8 | ${optionalString cfg.userControlled.enable ''
9 | ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}
10 | update_config=1''}
11 | ${cfg.extraConfig}
12 | ${concatStringsSep "\n" (mapAttrsToList (ssid: config: with config; let
13 | key = if psk != null
14 | then ''"${psk}"''
15 | else pskRaw;
16 | baseAuth = if key != null
17 | then ''psk=${key}''
18 | else ''key_mgmt=NONE'';
19 | in ''
20 | network={
21 | ssid="${ssid}"
22 | ${optionalString (priority != null) ''priority=${toString priority}''}
23 | ${optionalString hidden "scan_ssid=1"}
24 | ${if (auth != null) then auth else baseAuth}
25 | ${extraConfig}
26 | }
27 | '') cfg.networks)}
28 | '' else "/etc/wpa_supplicant.conf";
29 | in {
30 | options = {
31 | networking.wireless = {
32 | enable = mkEnableOption "wpa_supplicant";
33 |
34 | interfaces = mkOption {
35 | type = types.listOf types.str;
36 | default = [];
37 | example = [ "wlan0" "wlan1" ];
38 | description = ''
39 | The interfaces wpa_supplicant will use. If empty, it will
40 | automatically use all wireless interfaces.
41 | '';
42 | };
43 |
44 | driver = mkOption {
45 | type = types.str;
46 | default = "nl80211,wext";
47 | description = "Force a specific wpa_supplicant driver.";
48 | };
49 |
50 | networks = mkOption {
51 | type = types.attrsOf (types.submodule {
52 | options = {
53 | psk = mkOption {
54 | type = types.nullOr types.str;
55 | default = null;
56 | description = ''
57 | The network's pre-shared key in plaintext defaulting
58 | to being a network without any authentication.
59 |
60 | Be aware that these will be written to the nix store
61 | in plaintext!
62 |
63 | Mutually exclusive with pskRaw.
64 | '';
65 | };
66 |
67 | pskRaw = mkOption {
68 | type = types.nullOr types.str;
69 | default = null;
70 | description = ''
71 | The network's pre-shared key in hex defaulting
72 | to being a network without any authentication.
73 |
74 | Mutually exclusive with psk.
75 | '';
76 | };
77 |
78 | auth = mkOption {
79 | type = types.nullOr types.str;
80 | default = null;
81 | example = ''
82 | key_mgmt=WPA-EAP
83 | eap=PEAP
84 | identity="user@example.com"
85 | password="secret"
86 | '';
87 | description = ''
88 | Use this option to configure advanced authentication methods like EAP.
89 | See wpa_supplicant.conf(5) for example configurations.
90 |
91 | Mutually exclusive with psk and pskRaw.
92 | '';
93 | };
94 |
95 | hidden = mkOption {
96 | type = types.bool;
97 | default = false;
98 | description = ''
99 | Set this to true if the SSID of the network is hidden.
100 | '';
101 | };
102 |
103 | priority = mkOption {
104 | type = types.nullOr types.int;
105 | default = null;
106 | description = ''
107 | By default, all networks will get same priority group (0). If some of the
108 | networks are more desirable, this field can be used to change the order in
109 | which wpa_supplicant goes through the networks when selecting a BSS. The
110 | priority groups will be iterated in decreasing priority (i.e., the larger the
111 | priority value, the sooner the network is matched against the scan results).
112 | Within each priority group, networks will be selected based on security
113 | policy, signal strength, etc.
114 | '';
115 | };
116 |
117 | extraConfig = mkOption {
118 | type = types.str;
119 | default = "";
120 | example = ''
121 | bssid_blacklist=02:11:22:33:44:55 02:22:aa:44:55:66
122 | '';
123 | description = ''
124 | Extra configuration lines appended to the network block.
125 | See wpa_supplicant.conf(5) for available options.
126 | '';
127 | };
128 |
129 | };
130 | });
131 | description = ''
132 | The network definitions to automatically connect to when
133 | wpa_supplicant is running. If this
134 | parameter is left empty wpa_supplicant will use
135 | /etc/wpa_supplicant.conf as the configuration file.
136 | '';
137 | default = {};
138 | example = literalExample ''
139 | { echelon = {
140 | psk = "abcdefgh";
141 | };
142 | "free.wifi" = {};
143 | }
144 | '';
145 | };
146 |
147 | userControlled = {
148 | enable = mkOption {
149 | type = types.bool;
150 | default = false;
151 | description = ''
152 | Allow normal users to control wpa_supplicant through wpa_gui or wpa_cli.
153 | This is useful for laptop users that switch networks a lot and don't want
154 | to depend on a large package such as NetworkManager just to pick nearby
155 | access points.
156 |
157 | When using a declarative network specification you cannot persist any
158 | settings via wpa_gui or wpa_cli.
159 | '';
160 | };
161 |
162 | group = mkOption {
163 | type = types.str;
164 | default = "wheel";
165 | example = "network";
166 | description = "Members of this group can control wpa_supplicant.";
167 | };
168 | };
169 | extraConfig = mkOption {
170 | type = types.str;
171 | default = "";
172 | example = ''
173 | p2p_disabled=1
174 | '';
175 | description = ''
176 | Extra lines appended to the configuration file.
177 | See wpa_supplicant.conf(5) for available options.
178 | '';
179 | };
180 | };
181 | };
182 |
183 | config = mkIf cfg.enable {
184 | assertions = flip mapAttrsToList cfg.networks (name: cfg: {
185 | assertion = with cfg; count (x: x != null) [ psk pskRaw auth ] <= 1;
186 | message = ''options networking.wireless."${name}".{psk,pskRaw,auth} are mutually exclusive'';
187 | });
188 |
189 | environment.systemPackages = [ pkgs.wpa_supplicant ];
190 |
191 | services.dbus.packages = [ pkgs.wpa_supplicant ];
192 |
193 | # FIXME: start a separate wpa_supplicant instance per interface.
194 | systemd.services.wpa_supplicant = let
195 | ifaces = cfg.interfaces;
196 | deviceUnit = interface: [ "sys-subsystem-net-devices-${interface}.device" ];
197 | phys-aware = pkgs.writeScript "phys-aware" ''
198 | #! ${pkgs.bash}/bin/bash
199 | if ${pkgs.iproute}/bin/ip link | ${pkgs.gnugrep}/bin/grep -q wgvpn0;
200 | then exec ${pkgs.iproute}/bin/ip netns exec physical "$@"
201 | else exec "$@"
202 | fi
203 | '';
204 | scriptCore = pkgs.writeScript "wpa-supplicant-start" ''
205 | #! ${pkgs.bash}/bin/bash
206 | ${if ifaces == [] then ''
207 | for i in $(cd /sys/class/net && echo *); do
208 | DEVTYPE=
209 | source /sys/class/net/$i/uevent
210 | if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
211 | ifaces="$ifaces''${ifaces:+ -N} -i$i"
212 | fi
213 | done
214 | '' else ''
215 | ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
216 | ''}
217 | exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
218 | '';
219 | in {
220 | description = "WPA Supplicant";
221 |
222 | after = lib.concatMap deviceUnit ifaces;
223 | before = [ "network.target" ];
224 | wants = [ "network.target" ];
225 | requires = lib.concatMap deviceUnit ifaces;
226 | wantedBy = [ "multi-user.target" ];
227 | stopIfChanged = false;
228 |
229 | path = [ pkgs.wpa_supplicant ];
230 |
231 | script = ''
232 | exec ${phys-aware} ${scriptCore}
233 | '';
234 | };
235 |
236 | powerManagement.resumeCommands = ''
237 | ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant
238 | '';
239 |
240 | # Restart wpa_supplicant when a wlan device appears or disappears.
241 | services.udev.extraRules = ''
242 | ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service"
243 | '';
244 | };
245 |
246 | meta.maintainers = with lib.maintainers; [ globin ];
247 | }
248 |
--------------------------------------------------------------------------------
/dev-tools.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { environment.systemPackages = with pkgs; [
4 | (python3.buildEnv.override { extraLibs = [ python3Packages.ipython ]; })
5 | (haskellPackages.ghcWithPackages (p: with p; [ turtle ]))
6 | # android-studio
7 | aspell
8 | aria2
9 | awscli
10 | cmake
11 | # coq
12 | gcc
13 | gdb
14 | go
15 | gnumake
16 | ispell
17 | jq
18 | patchelf
19 | sqlite
20 | valgrind
21 | vscode
22 | z3
23 | ];
24 |
25 | environment.etc = {
26 | gitconfig.text = ''
27 | [user]
28 | email = anderspapitto@gmail.com
29 | name = Anders Papitto
30 | [pull]
31 | rebase = true
32 | [color]
33 | ui = auto
34 | [push]
35 | default = simple
36 | [merge]
37 | conflictstyle = diff3
38 | [core]
39 | excludesfile = /etc/gitignore
40 | '';
41 | gitignore.text = ''
42 | *.org
43 | *.org_archive
44 | '';
45 | "stack/config.yaml".text = ''
46 | templates:
47 | params:
48 | author-email: anderspapitto@gmail.com
49 | author-name: Anders Papitto
50 | github-username: anderspapitto
51 | nix:
52 | enable: false
53 | '';
54 | };
55 |
56 | # imports = [ ./rust-overlay.nix ];
57 | }
58 |
--------------------------------------------------------------------------------
/entrypoints/gurney.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { imports = [
4 | ./audio.nix
5 | ./android.nix
6 | ./base.nix
7 | ./dev-tools.nix
8 | ./fonts.nix
9 | ./games.nix
10 | ./gui-tools.nix
11 | ./hardware-configuration.nix
12 | ./inl-tools.nix
13 | ./laptop-base.nix
14 | ./networking.nix
15 | ./nix.nix
16 | ./nixpkgs.nix
17 | ./syncthing.nix
18 | ./sysadmin.nix
19 | ./uefi.nix
20 | ./utility-scripts.nix
21 | ./virtualization.nix
22 | ./wireguard-client.nix
23 | ./x.nix
24 |
25 | ./private/default.nix
26 | ];
27 |
28 | networking = {
29 | hostName = "gurney";
30 | hostId = "d9ebdbe0";
31 | };
32 |
33 | boot.initrd.luks.devices = [
34 | {
35 | name = "root";
36 | device = "/dev/disk/by-uuid/27cadee9-bc6c-4e62-9494-fa2f789bf98b";
37 | preLVM = true;
38 | allowDiscards = true;
39 | }
40 | ];
41 | }
42 |
--------------------------------------------------------------------------------
/entrypoints/thufir.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | let gurney-pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCt6axfh25SwAPkrTQlIJKqZkQ2zxxI6/a45Oa2uGclh2qjpic4egy4zQbHXCJOM8Baz9xfzmJDxWAhwckiiXYvG6W5bignIfx8F/z8P27Jganv9Np5GptG2E0tZKoSFXkCN7B3H4+/r4O6eWsx9mM8NzABIP6i+vqZ/5gaW1PUGBWX4yZRVKr9WbTGJp4R6txvW6aPaJKGOGqFCDqU9SzWC8uZFWOxcIMI/2gn0eW27cCL/ro1i4DDVMQsDnDqxJ6cHIKzNsQcGSGN8q67zPMFdxlrZ+9xnATkQxyRXuuU5xArusY+acWGUBa3lixfYTD9XFcgddctG3x6xwSHN9zx anders@gurney";
4 | in {
5 | imports =
6 | [ # Include the results of the hardware scan.
7 | ./hardware-configuration.nix
8 | ./base.nix
9 | ./sysadmin.nix
10 | ./nix.nix
11 | ];
12 |
13 | boot = {
14 | loader.grub = {
15 | enable = true;
16 | version = 2;
17 | device = "/dev/vda";
18 | };
19 | };
20 |
21 | environment.systemPackages = with pkgs; [ wireguard ];
22 |
23 | networking = {
24 | nat = {
25 | enable = true;
26 | externalInterface = "ens3";
27 | internalInterfaces = [ "wg0" ];
28 | };
29 | wireguard.interfaces = {
30 | wg0 = {
31 | ips = [ "10.100.0.1/24" ];
32 | listenPort = 51820;
33 | privateKeyFile = "/root/wireguard-keys/private";
34 | peers = [
35 | { publicKey = "qFE4Q7ieGRqUyEr2MDAd6rRhZkrJD3M3/dqSwwo+VTc=";
36 | allowedIPs = [ "10.100.0.2/32" ];
37 | }
38 | { publicKey = "ouX/+4ozC49/9xWJ5OuuhSB8zy4298XVrwUoIgLrQV8=";
39 | allowedIPs = [ "10.100.0.3/32" ];
40 | }
41 | ];
42 | };
43 | };
44 | hostName = "thufir";
45 | enableIPv6 = false;
46 | nameservers = [ "1.1.1.1" "8.8.8.8" ];
47 | firewall = {
48 | enable = true;
49 | extraCommands = ''
50 | iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE
51 | '';
52 | extraStopCommands = ''
53 | iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE
54 | '';
55 | allowedUDPPortRanges = [
56 | { from = 1194; to = 1195; } # openvpn
57 | { from = 60000; to = 61000; } # mosh
58 | { from = 51820; to = 51820; } # wireguard
59 | ];
60 | allowedTCPPorts = [ 4242 ]; # quassel
61 | trustedInterfaces = [ "tun0" "tun1" ];
62 | };
63 | };
64 |
65 | services = {
66 | fail2ban = {
67 | enable = true;
68 | };
69 | openssh = {
70 | enable = true;
71 | permitRootLogin = "yes";
72 | };
73 | gitolite = {
74 | enable = true;
75 | adminPubkey = gurney-pubkey;
76 | dataDir = "/var/lib/gitolite/gitolite";
77 | };
78 | openvpn = {
79 | servers = {
80 | laptop = {
81 | config = ''
82 | ifconfig 10.8.0.1 10.8.0.2
83 | dev tun0
84 | port 1194
85 | secret /root/static.key
86 | '';
87 | };
88 | phone = {
89 | config = ''
90 | ifconfig 10.8.0.1 10.8.0.3
91 | dev tun1
92 | port 1195
93 | secret /root/static.key
94 | '';
95 | };
96 | };
97 | };
98 | quassel = {
99 | enable = true;
100 | interfaces = [ "0.0.0.0" ];
101 | };
102 | syncthing = {
103 | enable = true;
104 | openDefaultPorts = true;
105 | };
106 | };
107 | }
108 |
--------------------------------------------------------------------------------
/fonts.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { i18n = {
4 | consoleFont = "lat9w-16";
5 | # consoleKeyMap = "colemak/en-latin9";
6 | defaultLocale = "en_US.UTF-8";
7 | };
8 |
9 | fonts = {
10 | enableFontDir = true;
11 | enableGhostscriptFonts = true;
12 | fonts = with pkgs; [
13 | corefonts
14 | inconsolata
15 | unifont
16 | ubuntu_font_family
17 | noto-fonts
18 | symbola
19 | ];
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/games.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { environment.systemPackages = with pkgs; [
4 | crawlTiles
5 | ];
6 | }
7 |
--------------------------------------------------------------------------------
/gui-tools.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { environment.systemPackages = with pkgs; [
4 | alacritty
5 | anki
6 | arandr
7 | # chromium
8 | clerk
9 | clipit
10 | dmenu
11 | evince
12 | firefox
13 | ghostscriptX
14 | glxinfo
15 | haskellPackages.hledger
16 | haskellPackages.hledger-web
17 | i3lock
18 | i3status
19 | imagemagick
20 | jmtpfs
21 | quasselClient
22 | libnotify
23 | ncmpcpp
24 | okular
25 | pass
26 | pavucontrol
27 | pianobar
28 | rofi
29 | # rxvt_unicode_with-plugins
30 | signal-desktop
31 | spotify
32 | st
33 | tdesktop
34 | tuxguitar
35 | vlc
36 | xdotool
37 | xlibs.xev
38 | # xsane
39 | xsel
40 | youtube-dl
41 | ];
42 | }
43 |
--------------------------------------------------------------------------------
/inl-tools.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | with pkgs;
4 |
5 | let bluetoothScript = scriptName: regexPattern:
6 | (writeScriptBin scriptName ''
7 | #! ${bash}/bin/bash
8 | set -x
9 |
10 | export XDG_RUNTIME_DIR=/run/user/$UID
11 |
12 | TRIES=0
13 | until (bluetoothctl <<< show | grep -q 'Powered: yes')
14 | do
15 | bluetoothctl <<< 'power on'
16 | [[ $((TRIES++)) -eq 20 ]] && exit 1
17 | sleep 0.1
18 | done
19 |
20 | TRIES=0
21 | until [ -n "$DEVICE" ]
22 | do
23 | DEVICE=$(bluetoothctl <<< devices | egrep '^Device.*${regexPattern}' | awk '{ print $2 }')
24 | [[ $((TRIES++)) -eq 20 ]] && exit 1
25 | sleep 0.1
26 | done
27 |
28 | TRIES=0
29 | until bluetoothctl <<< "connect $DEVICE"
30 | do
31 | [[ $((TRIES++)) -eq 20 ]] && exit 1
32 | sleep 0.1
33 | done
34 |
35 | TRIES=0
36 | until [ -n "$TARGET_CARD" ]
37 | do
38 | TARGET_CARD=$(pacmd list-cards | grep 'name:' | egrep -o 'bluez.*[^>]')
39 | [[ $((TRIES++)) -eq 20 ]] && exit 1
40 | sleep 0.1
41 | done
42 |
43 | TRIES=0
44 | until pacmd list-cards | egrep -q 'active profile: '
45 | do
46 | pacmd set-card-profile $TARGET_CARD a2dp_sink
47 | [[ $((TRIES++)) -eq 20 ]] && exit 1
48 | sleep 0.1
49 | done
50 |
51 | TRIES=0
52 | until [ -n "$TARGET_SINK" ]
53 | do
54 | TARGET_SINK=$(pacmd list-sinks | grep 'name:' | egrep -o 'bluez.*[^>]')
55 | [[ $((TRIES++)) -eq 20 ]] && exit 1
56 | sleep 0.1
57 | done
58 |
59 | pactl set-sink-volume $TARGET_SINK 50%
60 | pacmd set-default-sink $TARGET_SINK
61 |
62 | for index in $(pacmd list-sink-inputs $TARGET_SINK | grep index | awk '{ print $2 }')
63 | do
64 | pacmd move-sink-input $index $TARGET_SINK
65 | done
66 | '');
67 | in
68 | { environment.systemPackages = [
69 | (writeScriptBin "anders-handle-keybind" ''
70 | #! ${bash}/bin/bash
71 |
72 | case $1 in
73 | F1)
74 | pactl set-sink-mute @DEFAULT_SINK@ toggle
75 | killall -SIGUSR1 i3status
76 | ;;
77 | F2)
78 | pactl set-sink-volume @DEFAULT_SINK@ -5%
79 | killall -SIGUSR1 i3status
80 | ;;
81 | F3)
82 | pactl set-sink-volume @DEFAULT_SINK@ +5%
83 | killall -SIGUSR1 i3status
84 | ;;
85 | F7)
86 | exec systemctl suspend
87 | ;;
88 | F9)
89 | exec browser
90 | ;;
91 | F10)
92 | exec anders-capture
93 | ;;
94 | F11)
95 | exec i3-rename
96 | ;;
97 | F12)
98 | exec i3-switch
99 | ;;
100 | esac
101 | '')
102 | (writeScriptBin "i3-switch" ''
103 | #! ${bash}/bin/bash
104 |
105 | set -e
106 |
107 | list_workspaces() {
108 | ${i3}/bin/i3-msg -t get_workspaces | ${jq}/bin/jq -r '.[] | .name'
109 | }
110 |
111 | WORKSPACE=$( list_workspaces | rofi -dmenu -p "switch to workspace " )
112 |
113 | i3-msg workspace "$WORKSPACE"
114 | '')
115 | (writeScriptBin "i3-rename" ''
116 | #! ${bash}/bin/bash
117 |
118 | set -e
119 |
120 | NAME=$( rofi -dmenu -p "rename workspace to " )
121 |
122 | i3-msg "rename workspace to $NAME"
123 | '')
124 | (writeScriptBin "browser" ''
125 | #! ${bash}/bin/bash
126 | firefox "$@"
127 | exec i3-msg focus tiling
128 | '')
129 | (writeScriptBin "toggle-invert" ''
130 | #! ${bash}/bin/bash
131 | FOO=$( ${xdotool}/bin/xdotool getactivewindow getwindowname )
132 | if [[ $FOO == *" NOINVERT" ]];
133 | then
134 | FOO=''${FOO% NOINVERT};
135 | else
136 | FOO="$FOO NOINVERT";
137 | fi
138 | ${xdotool}/bin/xdotool getactivewindow set_window --name "$FOO"
139 | '')
140 | (writeScriptBin "global-toggle-invert" ''
141 | #! ${bash}/bin/bash
142 | . ${config.system.build.setEnvironment}
143 |
144 | if systemctl is-active compton-night > /dev/null
145 | then
146 | sudo systemctl start compton
147 | else
148 | sudo systemctl start compton-night
149 | fi
150 | '')
151 | (writeScriptBin "external-drive-mount" ''
152 | #! ${bash}/bin/bash
153 | set -x
154 | if [[ $EUID -ne 0 ]]; then
155 | echo "This script must be run as root" 1>&2
156 | exit 1
157 | fi
158 | ${cryptsetup}/bin/cryptsetup --type luks open /dev/sdb external
159 | mount -t ext4 /dev/mapper/external /mnt
160 | '')
161 | (writeScriptBin "external-drive-umount" ''
162 | #! ${bash}/bin/bash
163 | set -x
164 | if [[ $EUID -ne 0 ]]; then
165 | echo "This script must be run as root" 1>&2
166 | exit 1
167 | fi
168 | umount /mnt
169 | ${cryptsetup}/bin/cryptsetup close external
170 | '')
171 | (writeScriptBin "backup-homedir" ''
172 | #! ${bash}/bin/bash
173 | if [[ $EUID -eq 0 ]]; then
174 | echo "This script must not be run as root" 1>&2
175 | exit 1
176 | fi
177 | rsync -aAXHv $HOME/* /mnt
178 | '')
179 | # TODO remove my-pager in favor of anders-pager once i've rebooted
180 | (writeScriptBin "my-pager" ''
181 | #! ${bash}/bin/bash
182 | if [[ $TERM = dumb ]]; then
183 | exec cat "$@"
184 | else
185 | exec less -R "$@"
186 | fi
187 | '')
188 | (writeScriptBin "anders-pager" ''
189 | #! ${bash}/bin/bash
190 | if [[ $TERM = dumb ]]; then
191 | exec cat "$@"
192 | else
193 | exec less -R "$@"
194 | fi
195 | '')
196 | (writeScriptBin "editor" ''
197 | #! ${bash}/bin/bash
198 | exec nvim "$@"
199 | '')
200 | (writeScriptBin "disable-bluetooth" ''
201 | #! ${bash}/bin/bash
202 | set -x
203 |
204 | export XDG_RUNTIME_DIR=/run/user/$UID
205 |
206 | bluetoothctl <<< 'power off'
207 | '')
208 | (writeScriptBin "bluetooth-off" ''
209 | #! ${bash}/bin/bash
210 | set -x
211 | bluetoothctl <<< 'power off'
212 | '')
213 | (bluetoothScript "bluetooth-tranya" "T1-L")
214 | (bluetoothScript "bluetooth-oontz" "OontZ")
215 | (writeScriptBin "dark-mode" ''
216 | #! ${bash}/bin/bash
217 | set -x
218 | ${redshift}/bin/redshift -O 2000
219 | /run/wrappers/bin/sudo ${coreutils}/bin/tee /sys/class/backlight/intel_backlight/brightness <<< 250
220 | '')
221 | (writeScriptBin "twilight-mode" ''
222 | #! ${bash}/bin/bash
223 | set -x
224 | ${redshift}/bin/redshift -O 2500
225 | /run/wrappers/bin/sudo ${coreutils}/bin/tee /sys/class/backlight/intel_backlight/brightness <<< 500
226 | '')
227 | (writeScriptBin "bright-mode" ''
228 | #! ${bash}/bin/bash
229 | set -x
230 | ${redshift}/bin/redshift -x
231 | /run/wrappers/bin/sudo ${coreutils}/bin/tee /sys/class/backlight/intel_backlight/brightness <<< 852
232 | '')
233 |
234 | # (writeScriptBin "switch-to-headphones" ''
235 | # #! ${bash}/bin/bash
236 | # set -x
237 | # pacmd set-sink-port alsa_output.pci-0000_00_1b.0.analog-stereo analog-output-headphones
238 | # '')
239 | # (writeScriptBin "switch-to-speakers" ''
240 | # #! ${bash}/bin/bash
241 | # set -x
242 | # pacmd set-sink-port alsa_output.pci-0000_00_1b.0.analog-stereo analog-output-speaker
243 | # '')
244 | # (writeScriptBin "toggle-suspend-audio" ''
245 | # #! ${bash}/bin/bash
246 | # pacmd list-sinks | grep state: | grep -v -q SUSPENDED
247 | # if [[ $? -eq 0 ]]
248 | # then
249 | # pacmd suspend 1
250 | # else
251 | # pacmd suspend 0
252 | # fi
253 | # '')
254 | ];
255 |
256 | environment.variables = { PAGER = "anders-pager"; };
257 | }
258 |
--------------------------------------------------------------------------------
/laptop-base.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { hardware = {
4 | opengl.driSupport32Bit = true; # needed for steam and/or wine, i believe
5 | };
6 |
7 | services = {
8 | acpid.enable = true;
9 |
10 | logind.extraConfig = ''
11 | HoldoffTimeoutSec=0
12 | '';
13 | };
14 |
15 | systemd.services.battery_check = {
16 | description = "Send notification if battery is low";
17 | serviceConfig = {
18 | Type = "oneshot";
19 | User = "anders";
20 | ExecStart = pkgs.writeScript "battery_check" ''
21 | #!${pkgs.bash}/bin/bash --login
22 | . <(udevadm info -q property -p /sys/class/power_supply/BAT0 |
23 | grep -E 'POWER_SUPPLY_(CAPACITY|STATUS)=')
24 | if [[ $POWER_SUPPLY_STATUS = Discharging && $POWER_SUPPLY_CAPACITY -lt 15 ]];
25 | then notify-send -u critical "Battery is low: $POWER_SUPPLY_CAPACITY";
26 | fi
27 | '';
28 | };
29 | environment = { DISPLAY = ":0"; };
30 | after = [ "display-manager.service" ];
31 | startAt = "*:00/5";
32 | };
33 |
34 | users.extraUsers.anders = {
35 | isNormalUser = true;
36 | uid = 1000;
37 | extraGroups = [ "wheel" "audio" "docker" "redis" "adbusers" ];
38 | };
39 | }
40 |
--------------------------------------------------------------------------------
/networking.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { hardware.bluetooth.enable = true;
4 |
5 | networking = {
6 | extraHosts = ''
7 | 104.156.231.205 thufir
8 | '';
9 |
10 | dhcpcd.extraConfig = ''
11 | nohook resolv.conf
12 | noipv4ll
13 | '';
14 | enableIPv6 = false;
15 |
16 | nameservers = [ "1.1.1.1" "8.8.8.8" ];
17 | wireless.enable = true; # I directly use wpa_supplicant and dhcpcd
18 | };
19 |
20 | services.dnsmasq.enable = true;
21 | }
22 |
--------------------------------------------------------------------------------
/nix.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { nix = {
4 | buildCores = 0;
5 | daemonIONiceLevel = 4;
6 | daemonNiceLevel = 10;
7 | maxJobs = 8;
8 | extraOptions = ''
9 | auto-optimise-store = true
10 | gc-keep-outputs = true
11 | '';
12 | nixPath = [
13 | "/etc/nixos"
14 | "nixos-config=/etc/nixos/configuration"
15 | ];
16 | useSandbox = true;
17 | binaryCaches = [
18 | "https://cache.nixos.org"
19 | "https://nixcache.reflex-frp.org"
20 | "https://hie-nix.cachix.org"
21 | ];
22 | binaryCachePublicKeys = [
23 | "ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI="
24 | "hie-nix.cachix.org-1:EjBSHzF6VmDnzqlldGXbi0RM3HdjfTU3yDRi9Pd0jTY="
25 | ];
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/nixpkgs.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { nixpkgs.config = {
4 | allowUnfree = true;
5 |
6 | # chromium = {
7 | # enablePepperFlash = true;
8 | # };
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/rust-overlay.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | {
4 | nixpkgs.overlays = [
5 | (import /etc/nixos/overlays/nixpkgs-mozilla/rust-overlay.nix)
6 | ];
7 | environment.systemPackages = with pkgs; [
8 | rustChannels.beta.rust
9 | (llvm.override { enableSharedLibraries = true; })
10 | ];
11 | }
12 |
--------------------------------------------------------------------------------
/syncthing.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { services.syncthing = {
4 | enable = true;
5 | user = "anders";
6 | dataDir = "/home/anders/.syncthing";
7 | openDefaultPorts = true;
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/sysadmin.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | {
4 | boot = {
5 | # extraModulePackages = with config.boot.kernelPackages; [ sysdig ];
6 | };
7 |
8 | environment.systemPackages = with pkgs; [
9 | bind # provides `dig`
10 | binutils
11 | cryptsetup
12 | dmidecode
13 | dstat
14 | file
15 | git
16 | gptfdisk
17 | gnupg # emacs wants the gpg2 binary?
18 | htop
19 | iftop
20 | iotop
21 | linuxPackages.perf
22 | lshw
23 | lsof
24 | mosh
25 | mtr
26 | neovim
27 | neovim-remote
28 | neovim-qt
29 | nftables
30 | numactl
31 | openssl
32 | pciutils
33 | psmisc
34 | ripgrep
35 | # sysdig
36 | tcpdump
37 | tmux
38 | tree
39 | unzip
40 | wget
41 | which
42 | wireshark
43 | ];
44 | }
45 |
--------------------------------------------------------------------------------
/uefi.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { boot.loader = {
4 | systemd-boot.enable = true;
5 | efi.canTouchEfiVariables = true;
6 | };
7 | }
8 |
--------------------------------------------------------------------------------
/utility-scripts.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | let utility-scripts-src = pkgs.fetchFromGitHub {
4 | owner = "anderspapitto";
5 | repo = "utility-scripts";
6 | rev = "381f24ed1554561c929f96856b0c1e6c7cf4116c";
7 | sha256 = "042s7bwm1jff195ilz2wmhrarlz2ia63m9biinhb2wlg7rjb82ay";
8 | };
9 | in {
10 | environment.systemPackages = [
11 | (pkgs.callPackage "${utility-scripts-src}/nix-shell-wrapper" { })
12 | (pkgs.callPackage "${utility-scripts-src}/i3-focus" { })
13 | ];
14 | }
15 |
--------------------------------------------------------------------------------
/virtualization.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | { environment.systemPackages = with pkgs; [
4 | # docker
5 | ];
6 |
7 | networking.nat = {
8 | enable = true;
9 | internalInterfaces = ["ve-+"];
10 | externalInterface = "wlp4s0";
11 | };
12 |
13 | virtualisation = {
14 | # docker.enable = true;
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/wireguard-client.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | let
4 | physexec = pkgs.writeScriptBin "physexec" ''
5 | #! ${pkgs.bash}/bin/bash
6 | exec sudo -E ${pkgs.iproute}/bin/ip netns exec physical \
7 | sudo -E -u \#$(${pkgs.coreutils}/bin/id -u) \
8 | -g \#$(${pkgs.coreutils}/bin/id -g) \
9 | "$@"
10 | '';
11 | anders-i3status = pkgs.writeScriptBin "anders-i3status" ''
12 | #! ${pkgs.python3}/bin/python -u
13 |
14 | import os
15 | import signal
16 | import subprocess
17 |
18 | # https://stackoverflow.com/questions/320232/ensuring-subprocesses-are-dead-on-exiting-python-program
19 | os.setpgrp() # create new process group, become its leader
20 | try:
21 | p1 = subprocess.Popen(['physexec', 'i3status', '-c', '/etc/i3/status-netns'],
22 | stdout=subprocess.PIPE)
23 | p2 = subprocess.Popen([ 'i3status', '-c', '/etc/i3/status'],
24 | stdout=subprocess.PIPE)
25 |
26 | for i in range(2):
27 | line1 = p1.stdout.readline().decode('utf-8').strip()
28 | line2 = p2.stdout.readline().decode('utf-8').strip()
29 | print(line1)
30 | while True:
31 | line1 = p1.stdout.readline().decode('utf-8').strip()
32 | line2 = p2.stdout.readline().decode('utf-8').strip()
33 | print(line1.split(']')[0] + ', ' + line2.split('[')[1])
34 | finally:
35 | os.killpg(0, signal.SIGKILL) # kill all processes in my group
36 | '';
37 | in {
38 | # There's not really a better way to do this. Override these two services to
39 | # be wg-aware
40 | imports = [
41 | ./copied/dhcpcd.nix
42 | ./copied/wpa_supplicant.nix
43 | ];
44 | disabledModules = [
45 | "services/networking/dhcpcd.nix"
46 | "services/networking/wpa_supplicant.nix"
47 | ];
48 |
49 | environment.systemPackages = [ pkgs.wireguard physexec anders-i3status ];
50 |
51 | networking.wireless.interfaces = [ "wlp4s0" ];
52 |
53 | systemd.services = {
54 | physical-netns = {
55 | description = "physical namespace, for use with wireguard";
56 | wantedBy = [ "default.target" ];
57 | before = [ "display-manager.service" "network.target" ];
58 | serviceConfig = {
59 | Type = "oneshot";
60 | RemainAfterExit = true;
61 | ExecStart = "${pkgs.iproute}/bin/ip netns add physical";
62 | ExecStop = "${pkgs.iproute}/bin/ip netns del physical";
63 | };
64 | };
65 | wg0 = {
66 | description = "Wireguard interface, and vpn";
67 | requires = [ "physical-netns.service" ];
68 | after = [ "physical-netns.service" ];
69 | serviceConfig = {
70 | Type = "oneshot";
71 | RemainAfterExit = true;
72 | ExecStart = pkgs.writeScript "wgup" ''
73 | #! ${pkgs.bash}/bin/bash
74 |
75 | ${pkgs.iproute}/bin/ip -n physical link add wgvpn0 type wireguard
76 | ${pkgs.iproute}/bin/ip -n physical link set wgvpn0 netns 1
77 |
78 | ${pkgs.wireguard}/bin/wg set wgvpn0 \
79 | private-key /root/wireguard-keys/private \
80 | peer ghK62ZFGd9zkRPfF6JehK7OMAW6HMdy68RNalq9FVUo= \
81 | allowed-ips 0.0.0.0/0 \
82 | endpoint thufir:51820
83 | ${pkgs.iproute}/bin/ip link set wgvpn0 up
84 |
85 | ${pkgs.iproute}/bin/ip addr add 10.100.0.2/24 dev wgvpn0
86 | ${pkgs.iproute}/bin/ip route add default dev wgvpn0
87 |
88 | ${pkgs.iproute}/bin/ip link set enp0s25 netns physical
89 | ${pkgs.iw}/bin/iw phy phy0 set netns name physical
90 |
91 | ${pkgs.systemd}/bin/systemctl restart --no-block wpa_supplicant dhcpcd
92 | '';
93 | ExecStop = pkgs.writeScript "wgdown" ''
94 | #! ${pkgs.bash}/bin/bash
95 |
96 | ${pkgs.iproute}/bin/ip -n physical link set enp0s25 netns 1
97 | ${pkgs.iproute}/bin/ip netns exec physical ${pkgs.iw}/bin/iw phy phy0 set netns 1
98 |
99 | ${pkgs.iproute}/bin/ip link del wgvpn0
100 |
101 | ${pkgs.systemd}/bin/systemctl restart --no-block wpa_supplicant dhcpcd
102 | '';
103 | };
104 | };
105 |
106 | };
107 | }
108 |
--------------------------------------------------------------------------------
/x.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 |
3 | let dunstrc = builtins.toFile "dunstrc" (pkgs.lib.readFile ./config/dunstrc);
4 | background-image = pkgs.fetchurl {
5 | url = "http://orig01.deviantart.net/1810/f/2012/116/a/4/tranquility_by_andreewallin-d4xjtd0.jpg";
6 | sha256 = "17jcvy268aqcix7hb8acn9m9x7dh8ymb07w4f7s9apcklimz63bq";
7 | };
8 | solarized-theme = pkgs.fetchFromGitHub {
9 | owner = "anderspapitto";
10 | repo = "nixos-solarized-slim-theme";
11 | rev = "2822b7cb7074cf9aa36afa9b5cabd54105b3306c";
12 | sha256 = "0jp7qq02ly9wiqbgh5yamwd31ah1bbybida7mn1g6qpdijajf247";
13 | };
14 | simpleXService = name: description: execStart: {
15 | inherit description;
16 | environment = {
17 | DISPLAY = ":0";
18 | };
19 | serviceConfig = {
20 | Type = "simple";
21 | User = "anders";
22 | ExecStart = pkgs.writeScript name ''
23 | #! ${pkgs.bash}/bin/bash
24 | . ${config.system.build.setEnvironment}
25 | set -xe
26 | ${execStart}
27 | '';
28 | RestartSec = 3;
29 | Restart = "always";
30 | };
31 | wantedBy = [ "display-manager.service" ];
32 | after = [ "display-manager.service" ];
33 | };
34 | in {
35 | environment = {
36 | etc = {
37 | "compton/inverted" .source = ./config/compton-inverted;
38 | "compton/noninverted" .source = ./config/compton-noninverted;
39 | "dunst/dunstrc" .source = ./config/dunstrc;
40 | "i3/config" .source = ./config/i3;
41 | "i3/status" .source = ./config/i3status;
42 | "i3/status-netns" .source = ./config/i3status-netns;
43 | "X11/xresources" .source = ./config/xresources;
44 | };
45 | systemPackages = with pkgs; [ dzen2 gnupg ];
46 | };
47 |
48 | services = {
49 | xserver = {
50 | enable = true;
51 | desktopManager.xterm.enable = false;
52 | displayManager.slim.theme = solarized-theme;
53 | windowManager = {
54 | i3 = {
55 | enable = true;
56 | package = pkgs.i3-gaps;
57 | extraSessionCommands = ''
58 | ${pkgs.gnupg}/bin/gpg-connect-agent /bye
59 | export GPG_TTY=$(tty)
60 |
61 | sudo systemctl start openvpn-thufir &
62 | '';
63 | configFile = "/etc/i3/config";
64 | };
65 | default = "i3";
66 | };
67 | synaptics = {
68 | enable = true;
69 | tapButtons = false;
70 | twoFingerScroll = true;
71 | };
72 | layout = "us";
73 | # note typo in base.lst, where it says 'ctrl:ctrl_ralt' when it
74 | # means 'ctrl:ralt_rctrl'
75 | xkbOptions = "ctrl:ralt_rctrl, lv3:caps_switch";
76 | xkbVariant = "altgr-intl";
77 | };
78 | };
79 |
80 | systemd.services = {
81 | compton = simpleXService "compton"
82 | "lightweight compositing manager"
83 | "${pkgs.compton}/bin/compton -cCG --config /etc/compton/noninverted"
84 | ;
85 | compton-night =
86 | let base-service = simpleXService "compton-night"
87 | "lightweight compositing manager (night mode)"
88 | "${pkgs.compton}/bin/compton -cCG --config /etc/compton/inverted"
89 | ;
90 | in base-service // {
91 | conflicts = [ "compton.service" ];
92 | wantedBy = [ ];
93 | };
94 | dunst = simpleXService "dunst"
95 | "Lightweight libnotify server"
96 | "exec ${pkgs.dunst}/bin/dunst -config /etc/dunst/dunstrc"
97 | ;
98 | feh = simpleXService "feh"
99 | "Set background"
100 | ''
101 | ${pkgs.feh}/bin/feh --bg-fill --no-fehbg ${background-image}
102 | exec sleep infinity
103 | ''
104 | ;
105 | xbanish = simpleXService "xbanish"
106 | "xbanish hides the mouse pointer"
107 | "exec ${pkgs.xbanish}/bin/xbanish"
108 | ;
109 | clipit = simpleXService "clipit"
110 | "clipboard manager"
111 | "exec ${pkgs.clipit}/bin/clipit"
112 | ;
113 | xrdb = simpleXService "xrdb"
114 | "set X resources"
115 | ''
116 | ${pkgs.xorg.xrdb}/bin/xrdb /etc/X11/xresources
117 | exec sleep infinity
118 | '';
119 | };
120 | }
121 |
--------------------------------------------------------------------------------