dev.fron.io rc / e55db02
Add 'nixos/' from commit 'd1aecf3d4243fadcf9874c23909160d808072674' git-subtree-dir: nixos git-subtree-mainline: d166223b39f5d7248207bec1b33701dd7874777e git-subtree-split: d1aecf3d4243fadcf9874c23909160d808072674 Tony Olagbaiye 2 months ago
449 changed file(s) with 25002 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 ;;; Directory Local Variables
1 ;;; For more information see (info "(emacs) Directory Variables")
2
3 ((nil . (
4 ;(eval . (set (make-local-variable 'default-directory)
5 ; (locate-dominating-file buffer-file-name ".dir-locals.el")))
6 (compile-command . "env TERM=dumb nix run -vv '.#delta' --show-trace")
7 (eval . (setq projectile-project-compilation-cmd
8 "env TERM=dumb nix build --show-trace -vv && ./result && git push"))
9 )))
0 if [ -f flake.lock ] && [ -f flake.nix ]; then
1 # reload when these files change
2 watch_file flake.nix
3 watch_file flake.lock
4 # load the flake devShell
5 if [ ! -d $(direnv_layout_dir) ]; then
6 mkdir $(direnv_layout_dir)
7 fi
8 eval "$(nix --experimental-features 'nix-command flakes' print-dev-env --profile "$(direnv_layout_dir)/flake-profile")"
9 elif type lorri &>/dev/null; then
10 echo "direnv: using lorri from PATH ($(type -p lorri))"
11 eval "$(lorri direnv)"
12 else
13 # fall back to using direnv's builtin nix support
14 # to prevent bootstrapping problems.
15 use nix
16 fi
0 .gitattributes !filter !diff
0 result-*
1 result
2 .direnv/
3 .#
4 .git
0 flake.nix
0 ;; -*- mode: emacs-lisp; -*-
1 ;;; Directory Local Variables
2 ;;; For more information see (info "(emacs) Directory Variables")
3
4 ((nil . ((mode . nix))))
0 { pkgs, ... }: ''
1 # vim:syntax=apparmor
2 # ------------------------------------------------------------------
3 #
4 # Copyright (C) 2009 Canonical Ltd.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License published by the Free Software Foundation.
9 #
10 # ------------------------------------------------------------------
11
12 # system configuration
13 /usr/share/applications/ r,
14 /usr/share/applications/defaults.list mr,
15 /usr/share/applications/mimeinfo.cache mr,
16 /usr/share/applications/*.desktop mr,
17 /usr/share/icons/ r,
18 /usr/share/icons/** mr,
19 /usr/share/pixmaps/ r,
20 /usr/share/pixmaps/** mr,
21 /usr/local/share/icons/ r,
22 /usr/local/share/icons/** mr,
23 /usr/local/share/pixmaps/ r,
24 /usr/local/share/pixmaps/** mr,
25
26 # this should probably go elsewhere
27 /usr/share/mime/** mr,
28
29 # per-user configurations
30 owner @{HOME}/.icons/ r,
31 owner @{HOME}/.recently-used.xbel* mrw,
32 owner @{HOME}/.local/share/recently-used.xbel* rmw,
33 owner @{HOME}/.config/user-dirs.dirs mr,
34 owner @{HOME}/.config/mimeapps.list mr,
35 owner @{HOME}/.local/share/applications/ r,
36 owner @{HOME}/.local/share/applications/*.desktop mr,
37 owner @{HOME}/.local/share/applications/defaults.list mr,
38 owner @{HOME}/.local/share/applications/mimeapps.list mr,
39 owner @{HOME}/.local/share/applications/mimeinfo.cache mr,
40 owner @{HOME}/.local/share/icons/ r,
41 owner @{HOME}/.local/share/icons/** mr,
42 owner @{HOME}/.local/share/mime/ r,
43 owner @{HOME}/.local/share/mime/** mr,
44
45 # xorg caches
46 owner @{HOME}/.cache/mesa/** mrw,
47 ''
0 { pkgs, ... }: ''
1 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/audio"
2
3 # Started on-demand
4 /usr/bin/pulseaudio pxrm,
5
6 ## Site-local symlinks
7 #@{SYS_GIT}/sys/pulse/* r,
8 #@{SYS_GIT}/sys/asound.conf r,
9 #@{SYS_GIT}/sys/secure/pulse.cookie rk,
10
11 /tmp/orcexec.* m,
12 owner /run/user/*/orcexec.* rwkm,
13 deny owner @{HOME}/orcexec.* m,
14 ''
0 { pkgs, ... }: ''
1 deny /usr/bin/pulseaudio xrm,
2
3 deny /dev/shm/ r,
4 deny /run/user/*/pulse/ rw,
5 deny /usr/share/alsa/alsa.conf r,
6 deny /dev/snd/* rw,
7
8 deny /tmp/orcexec.* m,
9 deny /run/user/*/orcexec.* rwkm,
10 deny @{HOME}/orcexec.* m,
11
12 ## Site-local symlinks
13 #deny @{SYS_GIT}/sys/pulse/* r,
14 #deny @{SYS_GIT}/sys/asound.conf r,
15 #deny @{SYS_GIT}/sys/secure/pulse.cookie r,
16 ''
0 { pkgs, ... }: ''
1 /etc/machine-id r,
2
3 /sys/devices/system/cpu/ r,
4 /sys/devices/system/cpu/** r,
5
6 owner @{PROC}/@{pid}/stat r,
7 owner @{PROC}/@{pid}/cmdline r,
8
9 # compatibility .so files from old packages
10 /opt/compat/*.so* mr,
11
12 # Blacklist here shouldn't be relied upon for actual deny, only for audit
13 # private-tmp in wrapper scripts is the proper solution for not sharing stuff there
14 audit deny /tmp/{ssh,gpg}-*/** rwlkmx,
15 audit deny /tmp/{u,}screens/** rwlkmx,
16 audit deny /tmp/tmux-*/** rwlkmx,
17 audit deny /tmp/emacs*/** rwlkmx,
18 audit deny /tmp/systemd-*/** rwlkmx,
19 audit deny /tmp/claws-mail-*/** rwlkmx,
20 audit deny /tmp/efreetd_* rwlkmx,
21 ''
0 { pkgs, ... }: ''
1 /etc/pango/*/pango.modules r,
2 /etc/mailcap r,
3 #@{SYS_GIT}/app/X/drirc r,
4
5 #owner @{HOME_GIT}/fonts.conf r,
6 #owner @{HOME_GIT}/app_defaults.list r,
7 #owner @{HOME_GIT}/gtkrc-2.0 r,
8 #owner @{HOME_GIT}/gtkrc-3.0 r,
9 #owner @{HOME_GIT}/gtk-bookmarks-2.0 r,
10 #owner @{HOME_GIT}/gtk-bookmarks-3.0 r,
11 #owner @{HOME_GIT}/gtk-3.0.css r,
12 /usr/share/gtk-2.0/gtkrc r,
13 /usr/share/gtk-3.0/settings.ini r,
14
15 # Custom GTK3 theme/icon dirs
16 owner @{HOME}/.themes/ r,
17 owner @{HOME}/.themes/** r,
18 owner @{HOME}/.icons/ r,
19 owner @{HOME}/.icons/** r,
20
21 # Custom xdg icon path, specs and such stuff
22 owner @{HOME}/.xdg/** r,
23 #owner @{HOME_GIT}/xdg/** r,
24
25 # Disable gstreamer stuff, not used for anything relevant here
26 deny /usr/lib/gstreamer-*/gst-plugin-scanner x,
27 deny owner @{HOME}/.cache/gstreamer-*/ rw,
28 ''
0 { pkgs, ... }: ''
1 owner @{HOME}/[dD]ownload{,s}/ r,
2 owner @{HOME}/[dD]ownload{,s}/** rwl,
3 owner @{HOME}/@{XDG_DESKTOP_DIR}/ r,
4 owner @{HOME}/@{XDG_DESKTOP_DIR}/* rwl,
5 owner @{HOME}/@{XDG_DOWNLOAD_DIR}/ r,
6 owner @{HOME}/@{XDG_DOWNLOAD_DIR}/* rwl,
7 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2002-2009 Novell/SUSE
4 # Copyright (C) 2009-2010 Canonical Ltd.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License published by the Free Software Foundation.
9 #
10 # ------------------------------------------------------------------
11
12 # per-user tmp directories
13 owner @{HOME}/tmp/** rwkl,
14 owner @{HOME}/tmp/ rw,
15
16 # global tmp directories
17 owner /var/tmp/** rwkl,
18 /var/tmp/ rw,
19 owner /tmp/** rwkl,
20 /tmp/ rw,
21 ''
0 { pkgs, ... }: ''
1 # vim:syntax=apparmor
2 # ------------------------------------------------------------------
3 #
4 # Copyright (C) 2012 Canonical Ltd.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License published by the Free Software Foundation.
9 #
10 # ------------------------------------------------------------------
11
12 # Entries based on:
13 # http://standards.freedesktop/basedir-spec/basedir-spec-latest.html
14
15 owner @{HOME}/.cache/ rw,
16
17 owner @{HOME}/.config/ rw,
18
19 owner @{HOME}/.local/ rw,
20 owner @{HOME}/.local/share/ rw,
21
22 # fallbacks
23 /usr/share/ r,
24 /usr/local/share/ r,
25 ''
0 { pkgs, ... }: ''
1 # For component build of brave in particular
2
3 include <tunables/global>
4
5 profile /usr/lib/brave/brave {
6 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
7 include <abstractions/site/base>
8 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
9 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
10 include <abstractions/pulse>
11 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/gnome"
12 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
13 include <abstractions/user-download>
14 include <abstractions/ssl-certs>
15 include <abstractions/site/de>
16 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dconf"
17
18
19 ### Main binary and sandboxing setup
20
21 /usr/lib/brave/brave ix,
22 /usr/lib/brave/** mr,
23 /usr/lib/brave/brave mr,
24 deny /usr/bin/xdg-{settings,desktop-menu} x, # "default browser" stuff
25
26 # sandbox/linux/services/namespace_sandbox.cc credentials.cc
27 capability sys_admin sys_chroot sys_ptrace,
28 signal (receive) peer=unconfined,
29 deny signal (send) peer=unconfined,
30 @{PROC}/sys/kernel/yama/ptrace_scope r,
31 deny ptrace, # triggers on xdg handlers
32
33
34 ### Main profile dirs, shm and various fs caches
35
36 deny /etc/opt/ rw, # tries to create it
37
38 /etc/chromium/** rk, # policies/managed and such
39 owner @{HOME}/.pki/nssdb/** rwk,
40 owner @{HOME}/.cache/thumbnails/** rw,
41 owner @{HOME}/.{config,cache}/BraveSoftware/ rwk,
42 owner @{HOME}/.{config,cache}/BraveSoftware/** rwk,
43 owner @{HOME}/.cache/mesa_shader_cache/** rwk,
44
45 deny /usr/lib/brave/extensions/ rw,
46
47 # Chromium fills these paths with gigs of trash fast, not sure if Brave does too
48 deny @{HOME}/.config/BraveSoftware/BrowserMetrics/ rw,
49 deny @{HOME}/.config/BraveSoftware/BrowserMetrics/** rw,
50 deny @{HOME}/.config/BraveSoftware/BrowserMetrics* rw,
51
52 # Site-local stuff
53 #@{SYS_GIT}/app/X/vdpau_wrapper.cfg r,
54
55 /{run,dev}/shm/.org.chromium.Chromium.* rwkm,
56 /{run,dev}/shm/org.chromium.Chromium.shmem.* rwkm,
57
58
59 ### Misc optional access
60
61 # File selection dialogs
62 deny @{HOME} r,
63 /etc/fstab r,
64 /run/mount/utab r,
65 @{PROC}/@{pid}/mountinfo r,
66 /usr/share/glib-*/schemas/gschemas.compiled r,
67 deny /{,var/}run/user/*/dconf/user w,
68
69 # Platform stats/fingerprinting
70 deny /etc/os-release r,
71 deny /sys/devices/virtual/dmi/id/* r,
72
73 # Imports from other browsers/apps
74 deny @{HOME}/.config/chromium/** rw,
75
76 # StorageMonitorLinux for Media Gallery API - http://crbug.com/141229
77 deny /run/udev/data/** r,
78 deny /sys/devices/virtual/tty/tty*/active r,
79 deny /sys/class/*/ r,
80
81 # V4L2 video API
82 deny /dev/video* r,
83
84
85 ### /proc and /dev
86
87 @{PROC}/ r,
88 owner @{PROC}/@{pid}/fd/ r,
89 @{PROC}/vmstat r,
90 @{PROC}/sys/fs/inotify/max_user_watches r,
91 @{PROC}/@{pids}/stat r,
92 owner @{PROC}/@{pid}/setgroups w,
93 owner @{PROC}/@{pid}/gid_map w,
94 owner @{PROC}/@{pid}/uid_map w,
95 owner @{PROC}/@{pid}/{mem,stat,statm} r,
96 owner @{PROC}/@{pid}/clear_refs w,
97 owner @{PROC}/@{pid}/task/ r,
98 owner @{PROC}/@{pid}/task/@{pids}/stat r,
99 owner @{PROC}/@{pid}/task/@{pids}/status r,
100
101 deny /sys/devices/virtual/tty/tty*/active r,
102 deny @{PROC}/@{pid}/oom_{,score_}adj rw,
103
104 # Device access stuff - should allow for GPU, but nothing else, ideally
105 /dev/ r,
106 /etc/udev/udev.conf r,
107 /sys/{bus,class}/ r,
108 /sys/bus/pci/devices/ r,
109 /sys/devices/pci[0-9:.]*/**/{uevent,resource,irq,vendor,device,class} r,
110 /sys/devices/pci[0-9:.]*/**/{subsystem_vendor,subsystem_device,config} r,
111 /sys/devices/pci[0-9:.]*/**/drm/ r,
112
113 # Wildcard rule doesn't work here, as it overrides "/sys/bus/pci/devices/ r"
114 deny /sys/bus/{clockevents,dax,platform,pci_express,serio,event_source}/devices/ r,
115 deny /sys/bus/{machinecheck,cpu,hdaudio,scsi,clocksource,hid,edac}/devices/ r,
116 deny /sys/bus/{pnp,usb,workqueue,virtio,container,acpi,i2c,snd_seq,mipi-dsi}/devices/ r,
117 deny /sys/bus/{mdio_bus,nvmem,wmi,usb-serial}/devices/ r,
118
119
120 ### Network
121
122 network inet dgram,
123 network inet stream,
124
125 }
126 ''
0 { pkgs, ... }: ''
1 # For https://github.com/Eloston/ungoogled-chromium variant of chromium
2
3 # NOTE: assumes kernel support for ns-sandbox, and not suid-sandbox
4 # modern chromium uses ns-sandbox if it can, with suid as a fallback
5 # see also: https://bugs.chromium.org/p/chromium/issues/detail?id=312380
6
7 include <tunables/global>
8
9 profile ${pkgs.chromium}/bin/chromium {
10 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
11 include <abstractions/site/base>
12
13 ${pkgs.chromium.browser}/libexec/chromium/chromium cx -> chromium,
14
15 profile chromium {
16 include "${pkgs.apparmorRulesFromClosure { name = "chromium"; } [
17 pkgs.chromium
18 ]}"
19 include <local/bin.chromium>
20 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
21 include <abstractions/site/base>
22 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
23 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
24 include <abstractions/pulse>
25 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/gnome"
26 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
27 include <abstractions/user-download>
28 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ssl_certs"
29 include <abstractions/site/de>
30 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dconf"
31
32 ${pkgs.chromium.browser}/libexec/chromium/chromium ix,
33 ${pkgs.chromium.browser}/libexec/chromium/** mr,
34 ${pkgs.chromium.browser}/libexec/chromium/chromium mr,
35 deny {/run/current-system/sw,/etc/profiles/per-user/*}/bin/xdg-{settings,desktop-menu} x, # "default browser" stuff
36
37 @{PROC}/ r,
38 owner @{PROC}/@{pid}/fd/ r,
39 deny @{PROC}/@{pid}/oom_{,score_}adj rw,
40
41 # sandbox/linux/services/namespace_sandbox.cc credentials.cc
42 capability sys_admin,
43 capability sys_chroot,
44 signal (receive) peer=unconfined,
45 deny signal (send) peer=unconfined,
46
47 # Presumably for built-in debugger/crash-report
48 capability sys_ptrace,
49 @{PROC}/@{pid}/status r,
50 @{PROC}/sys/kernel/yama/ptrace_scope r,
51 deny ptrace, # triggers on xdg handlers
52
53 /etc/chromium/** rk, # policies/managed and such
54 owner @{HOME}/.pki/nssdb/** rwk,
55 owner @{HOME}/.cache/thumbnails/** rw,
56 owner @{HOME}/.{config,cache}/chromium/ rwk,
57 owner @{HOME}/.{config,cache}/chromium/** rwk,
58 owner @{HOME}/.cache/mesa_shader_cache/** rwk,
59 /{run,dev}/shm/.org.chromium.Chromium.* rwkm,
60 /{run,dev}/shm/org.chromium.Chromium.shmem.* rwkm,
61
62 # Fills these paths with gigs of trash fast otherwise
63 deny @{HOME}/.config/chromium/BrowserMetrics/ rw,
64 deny @{HOME}/.config/chromium/BrowserMetrics/** rw,
65 deny @{HOME}/.config/chromium/BrowserMetrics* rw,
66
67 @{PROC}/vmstat r,
68 @{PROC}/sys/fs/inotify/max_user_watches r,
69 @{PROC}/@{pids}/stat r,
70 owner @{PROC}/@{pid}/setgroups w,
71 owner @{PROC}/@{pid}/gid_map w,
72 owner @{PROC}/@{pid}/uid_map w,
73 owner @{PROC}/@{pid}/{mem,stat,statm} r,
74 owner @{PROC}/@{pid}/clear_refs w,
75 owner @{PROC}/@{pid}/task/ r,
76 owner @{PROC}/@{pid}/task/@{pids}/stat r,
77 owner @{PROC}/@{pid}/task/@{pids}/status r,
78
79 deny ${pkgs.chromium.browser}/libexec/chromium/extensions/ rw,
80
81 # Device access stuff - should allow for GPU, but nothing else, ideally
82 /dev/ r,
83 /etc/udev/udev.conf r,
84 /sys/{bus,class}/ r,
85 /sys/bus/pci/devices/ r,
86 /sys/devices/pci[0-9:.]*/**/{uevent,resource,irq,vendor,device,class} r,
87 /sys/devices/pci[0-9:.]*/**/{subsystem_vendor,subsystem_device,config} r,
88 deny /sys/devices/pci[0-9:.]*/**/descriptors r, # block any further android-debug checks
89 deny /dev/video* r,
90
91 # Other known device-query things:
92 # - StorageMonitorLinux for Media Gallery API - http://crbug.com/141229
93 deny /run/udev/data/** r,
94 deny /sys/devices/virtual/tty/tty*/active r,
95 deny /sys/class/*/ r,
96
97 # Wildcard rule doesn't work here, as it overrides "/sys/bus/pci/devices/ r"
98 deny /sys/bus/{clockevents,dax,platform,pci_express,serio,event_source}/devices/ r,
99 deny /sys/bus/{machinecheck,cpu,hdaudio,scsi,clocksource,hid,edac}/devices/ r,
100 deny /sys/bus/{pnp,usb,workqueue,virtio,container,acpi,i2c,snd_seq,mipi-dsi}/devices/ r,
101 deny /sys/bus/{mdio_bus,nvmem,wmi,usb-serial}/devices/ r,
102
103 # URL handlers
104 #owner @{HOME_BIN}/wrappers/xdg-open Ux,
105 #owner @{HOME_BIN}/wrappers/leech_*.wrapper Ux,
106
107 # File selection dialogs
108 deny @{HOME} r,
109 /etc/fstab r,
110 /run/mount/utab r,
111 @{PROC}/@{pid}/mountinfo r,
112 /usr/share/glib-*/schemas/gschemas.compiled r,
113 deny /{,var/}run/user/*/dconf/user w,
114
115 # Import for bookmarks and such
116 deny @{HOME}/.mozilla/firefox/ rw,
117 deny @{HOME}/.mozilla/firefox/** rw,
118
119 # Weird mmap probes
120 deny @{HOME}/#[0-9]* m,
121 /tmp/#[0-9]* m,
122
123 # All network
124 network inet dgram,
125 network inet stream,
126 }
127
128 }
129 ''
0 args@{ config, pkgs, lib, ... }:
1
2 # Done manually until i feel like something similarly hacky to ../emacs
3 {
4 policies = lib.mapAttrs (_: nix: import nix args) {
5 #"bin.brave" = ./brave;
6 "bin.chromium" = ./chromium;
7 #"bin.electricsheep" = ./electricsheep;
8 #"bin.firefox" = ./firefox;
9 #"bin.nginx" = ./nginx;
10 #"bin.pulseaudio" = ./pulseaudio;
11 #"bin.skype" = ./skypeforlinux;
12 #"bin.upwork" = ./upwork;
13 #"bin.waterfox" = ./waterfox;
14 #"bin.wine" = ./wine;
15 #"home..nw" = ./node-webkit;
16 };
17 includes = lib.mapAttrs (_: nix: import nix args) {
18 "abstractions/freedesktop" = ./abstractions/freedesktop;
19 "abstractions/site/base" = ./abstractions/site/base;
20 "abstractions/site/de" = ./abstractions/site/de;
21 "abstractions/pulse" = ./abstractions/pulse;
22 "abstractions/pulse-deny" = ./abstractions/pulse-deny;
23 "abstractions/user-download" = ./abstractions/user-download;
24 "abstractions/user-tmp" = ./abstractions/user-tmp;
25 "abstractions/xdg-desktop" = ./abstractions/xdg-desktop;
26 "abstractions/tunables/home.d/site.git" = ./tunables/home.d/site.git;
27 "abstractions/tunables/home.d/site.local" = ./tunables/home.d/site.local;
28 "abstractions/tunables/xdg-user-dirs.d/site.local" = ./tunables/xdg-user-dirs.d/site.local;
29 "abstractions/tunables/apparmorfs" = ./tunables/apparmorfs;
30 "abstractions/tunables/dovecot" = ./tunables/dovecot;
31 "abstractions/tunables/global" = ./tunables/global;
32 "abstractions/tunables/home" = ./tunables/home;
33 "abstractions/tunables/kernelvars" = ./tunables/kernelvars;
34 "abstractions/tunables/ntpd" = ./tunables/ntpd;
35 "abstractions/tunables/proc" = ./tunables/proc;
36 "abstractions/tunables/securityfs" = ./tunables/securityfs;
37 "abstractions/tunables/sys" = ./tunables/sys;
38 "abstractions/tunables/xdg-user-dirs" = ./tunables/xdg-user-dirs;
39 };
40 }
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /usr/bin/electricsheep {
4 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
6 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
7 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/bash"
8 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/consoles"
9 include <abstractions/site/base>
10 include <abstractions/site/de>
11
12 /usr/bin/bash ix,
13 /usr/bin/xset ix,
14 /usr/bin/which ix,
15
16 /usr/share/electricsheep/ r,
17 /usr/share/electricsheep/** r,
18 @{HOME}/.electricsheep/ rwk,
19 @{HOME}/.electricsheep/** rwk,
20
21 network,
22 }
23 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 # /usr/lib/firefox/firefox flags=( complain ) {
4 /usr/lib/firefox/firefox {
5
6 include <abstractions/pulse>
7 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
8 include <abstractions/ssl-certs>
9 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/gnome"
10 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dconf"
11 include <abstractions/user-download>
12 include <abstractions/freedesktop>
13 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/consoles"
14 include <abstractions/site/base>
15 include <abstractions/site/de>
16
17 # Launcher
18 /dev/tty* rw,
19 /usr/{lib/firefox,bin}/firefox rix,
20 /usr/lib/xulrunner/xulrunner-stub ix,
21
22 owner @{HOME}/.mozilla/firefox/** rwk,
23 owner @{HOME}/.cache/ rw,
24 owner @{HOME}/.cache/mozilla/ rw,
25 owner @{HOME}/.cache/mozilla/firefox/ rw,
26 owner @{HOME}/.cache/mozilla/firefox/** rwk,
27 owner @{HOME}/.cache/gstreamer-*/ rw,
28 owner @{HOME}/.cache/gstreamer-*/** rw,
29 owner @{HOME}/.cache/thumbnails/** rw,
30
31 /opt/netscape/plugins/ r,
32 /opt/netscape/plugins/** mr,
33 owner @{HOME}/.mozilla/plugins/ r,
34 owner @{HOME}/.mozilla/plugins/** mr,
35 owner @{HOME}/.mozilla/firefox/*/extensions/** m,
36 owner @{HOME}/.mozilla/extensions/** mr,
37
38 # Didn't check what this one is for
39 deny @{HOME}/.mozilla/systemextensionsdev/ rw,
40 deny @{HOME}/.mozilla/systemextensionsdev/** rw,
41
42 /etc/mime.types r,
43 /etc/mailcap r,
44 /usr/share/ r,
45 /usr/share/mime/ r,
46 /usr/share/glib-*/schemas/* r,
47 /usr/share/applications/screensavers/ r,
48 owner @{HOME}/.local/share/ r,
49 owner @{HOME}/.local/share/applications/ r,
50 owner @{HOME}/.local/share/applications/** r,
51
52 owner @{PROC}/@{pid}/fd/ r,
53 owner @{PROC}/@{pid}/mountinfo r,
54 owner @{PROC}/@{pid}/statm r, # for about:memory
55 owner @{PROC}/@{pid}/task/[0-9]*/stat r,
56 @{PROC}/@{pid}/net/arp r, # for local "network id", to detect changes
57
58 # udev
59 /etc/udev/udev.conf r,
60 /sys/devices/**/name r,
61 /sys/devices/**/uevent r,
62 /run/udev/data/* r,
63 /run/mount/utab r,
64 /sys/{bus,class}/ r,
65 /sys/class/{drm,input}/ r,
66 deny /dev/ r,
67 deny /sys/devices/pci**/{config,vendor,device} r,
68
69 # Used in private mode
70 /usr/bin/shred ix,
71
72 # Allowing to change these doesn't seem to be a good idea
73 # And denying it should be harmless
74 deny /{,var/}run/user/*/dconf/user w,
75 deny @{HOME}/.config/dconf/user w,
76 deny /var/cache/fontconfig/ w,
77 deny @{HOME}/.cache/fontconfig/** w,
78 deny /usr/lib/firefox/fonts/** w,
79
80 ## Site-local paths
81 # Images in file selection dialogs
82 owner @{HOME}/.thumbnails/** w,
83 # Download handlers
84 #owner @{HOME_BIN}/wrappers/leech_*.wrapper Ux,
85 deny /usr/bin/bash x, # flashgot leechers' detection
86 # It's All Text
87 #owner @{HOME_GIT}bin/ec Ux,
88 # downloads
89 /etc/fstab r,
90
91 ## New e10s profiles
92 /usr/lib/firefox/plugin-container ix, # used to create new tab
93 audit deny /dev/shm/org.chromium.Chromium.* rw, # used by Chromium
94 owner /dev/shm/org.chromium.* rwmk,
95
96 }
97 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /usr/bin/nginx {
4 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
6
7 /etc/nginx/** r,
8 /etc/ssl/** r,
9 /etc/core/** r, # site-local config dir
10
11 /run/nginx.pid rwk,
12 /var/{log,lib,cache}/nginx/** rwmk,
13 /run/uwsgi/** rw,
14
15 /usr/share/nginx/html r,
16 /usr/share/nginx/html/** r,
17 /srv/www r,
18 /srv/www/** r,
19 /var/empty r,
20 /var/empty/** r,
21
22 # Checks for lot of capabilities on start, fails if check is denied
23 capability dac_read_search dac_override net_bind_service setuid setgid,
24 /proc/sys/kernel/random/boot_id r,
25
26 network inet tcp,
27 network inet udp,
28 network inet icmp,
29 }
30 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /home/*/.nw/nw {
4
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
6 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
7 include <abstractions/pulse>
8 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
9 include <abstractions/node-webkit>
10 include <abstractions/site/base>
11 include <abstractions/site/de>
12
13 owner @{HOME}/.nw/ r,
14 owner @{HOME}/.nw/** mr,
15 owner @{HOME}/.nw/nw ix,
16 owner @{HOME}/.nw/config/** mrwk,
17
18 owner @{HOME}/.config/node-webkit/ rw,
19 owner @{HOME}/.config/node-webkit/** rwmk,
20
21 ## planetscape app
22 / r,
23 /usr/bin/mtr Ux,
24 /usr/bin/ss Ux,
25
26 network,
27
28 }
29 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /usr/bin/pulseaudio {
4
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
6 include <abstractions/user-tmp>
7 include <abstractions/pulse>
8 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
9 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
10 include <abstractions/freedesktop>
11 include <abstractions/site/base>
12
13 /usr/lib/pulse-*/modules/* m,
14 /usr/share/pulseaudio/** r,
15
16 /etc/udev/udev.conf r,
17 /run/udev/data/* r,
18
19 /tmp/pulse-* k,
20 /tmp/pulse-*/* k,
21 /run/udev/queue.bin r,
22 /run/systemd/users/* r,
23
24 owner /run/user/*/pulse/* rwk,
25
26 owner @{HOME}/.config/pulse/ rwk,
27 owner @{HOME}/.config/pulse/** rwk,
28 owner @{HOME}/.esd_auth r,
29
30 owner @{PROC}/@{pid}/fd/ r,
31 owner @{PROC}/@{pid}/fd/* r,
32 owner @{PROC}/@{pid}/mountinfo r,
33
34 /sys/bus/ r,
35 /sys/class/ r,
36 /sys/class/sound/ r,
37 /sys/devices/virtual/dmi/id/*_vendor r,
38 /sys/devices/**/sound/** r,
39 /dev/input/event* r, # module-mmkbd-evdev
40
41 network tcp,
42 network udp,
43
44 ## Site-local symlinks
45 /etc/alsa/conf.d/ r,
46 /etc/alsa/conf.d/* r,
47 #@{SYS_GIT}/sys/pulse/* r,
48 #@{SYS_GIT}/sys/asound.conf r,
49 #@{SYS_GIT}/sys/secure/pulse.cookie rk,
50 # No need to ever write new cookies there:
51 deny /etc/pulse/auth.tcp.cookie w,
52 #deny @{SYS_GIT}/sys/secure/pulse.cookie w,
53
54 ## JACK integration via module-jack-*
55 /dev/shm/jack-*/** rw,
56 /usr/bin/bash px -> pulse_jackd_sh,
57
58 }
59
60 # Only purpose of these is to run "jackd -l"
61 profile pulse_jackd_sh {
62 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
63 include <abstractions/site/base>
64 /usr/bin/bash rm,
65 deny /dev/** rw,
66 /usr/bin/jackd px -> pulse_jackd_check,
67 }
68 profile pulse_jackd_check {
69 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
70 include <abstractions/site/base>
71 /usr/bin/jackd rm,
72 }
73 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /usr/share/skypeforlinux/skypeforlinux {
4
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
6 include <abstractions/site/base>
7 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
8 include <abstractions/ssl-certs>
9 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
10 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
11 include <abstractions/freedesktop>
12 include <abstractions/user-download>
13 include <abstractions/pulse>
14 include <abstractions/site/de>
15
16 /usr/share/skypeforlinux/** kmr,
17 /usr/share/skypeforlinux/skypeforlinux ix,
18
19 owner @{HOME}/.config/skypeforlinux/ rw,
20 owner @{HOME}/.config/skypeforlinux/** krwm,
21 owner @{HOME}/[dD]ownload{,s}/** k,
22
23 capability sys_admin sys_chroot sys_ptrace,
24 signal (receive) peer=unconfined,
25 deny signal (send) peer=unconfined,
26
27 @{PROC}/ r,
28 @{PROC}/vmstat r,
29 @{PROC}/sys/fs/inotify/max_user_watches r,
30 @{PROC}/@{pids}/stat r,
31 owner @{PROC}/@{pid}/fd/ r,
32 owner @{PROC}/@{pid}/setgroups w,
33 owner @{PROC}/@{pid}/gid_map w,
34 owner @{PROC}/@{pid}/uid_map w,
35 owner @{PROC}/@{pid}/{mem,stat,statm} r,
36 owner @{PROC}/@{pid}/clear_refs w,
37 owner @{PROC}/@{pid}/task/ r,
38 owner @{PROC}/@{pid}/task/@{pids}/stat r,
39 owner @{PROC}/@{pid}/task/@{pids}/status r,
40
41 /dev/shm/shm-* rwkm, # required for screen sharing
42 /tmp/.org.chromium.Chromium.*/ rw,
43 /tmp/.org.chromium.Chromium.*/** rwmk,
44 /{run,dev}/shm/.org.chromium.Chromium.* rwkm,
45 /{run,dev}/shm/org.chromium.Chromium.shmem.* rwkm,
46
47 /dev/ r,
48 /sys/bus/pci/devices/ r,
49 /sys/devices/pci[0-9:.]*/**//net/*/speed r,
50
51 deny /dev/video* r,
52
53 deny /etc/passwd rm,
54 deny /proc/sys/kernel/yama/ptrace_scope r,
55 deny @{HOME}/.config/autostart/** w, # autostart
56 deny @{HOME}/.pki/** rw,
57 deny @{HOME}/.rnd r,
58 deny /tmp/skypeforlinux*/ rwkm, # crash dumps
59 deny /tmp/skype-*/ rwkm, # probably locks, doesn't clean these up
60
61 # Platform stats and fingerprinting on startup
62 # None of these seem to be necessary in any way
63 deny /dev/pts/* rw,
64 deny /sys/devices/virtual/tty/tty*/active r,
65 deny /etc/os-release r,
66 deny /proc/sys/kernel/random/boot_id r,
67 deny /usr/bin/locale x,
68 deny /proc/sys/kernel/ostype r,
69 deny /proc/sys/kernel/osrelease r,
70 deny /proc/version r,
71 deny /sys/devices/pci[0-9:.]*/**/{resource,irq} r,
72 deny /sys/devices/virtual/dmi/id/board_vendor r,
73 deny /sys/devices/virtual/dmi/id/product_name r,
74 deny /etc/issue r,
75 deny /etc/hostname r,
76 deny /dev/disk/by-id/ r,
77 deny /sys/class/net/ r,
78 deny /sys/devices/virtual/net/** r,
79
80 network inet dgram,
81 network inet stream,
82
83 }
84 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2010 Canonical Ltd.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of version 2 of the GNU General Public
7 # License published by the Free Software Foundation.
8 #
9 # ------------------------------------------------------------------
10
11 # Alias rules can be used to rewrite paths and are done after variable
12 # resolution. For example, if '/usr' is on removable media:
13 # alias /usr/ -> /mnt/usr/,
14 #
15 # Or if mysql databases are stored in /home:
16 # alias /var/lib/mysql/ -> /home/mysql/,
17 ''
0 { pkgs, ... }: ''
1 # Copyright (C) 2012 Canonical Ltd.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of version 2 of the GNU General Public
5 # License published by the Free Software Foundation.
6 #
7 # ------------------------------------------------------------------
8
9 include <tunables/securityfs>
10
11 @{apparmorfs}=@{securityfs}/apparmor/
12 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2013 Christian Boltz
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of version 2 of the GNU General Public
7 # License published by the Free Software Foundation.
8 #
9 # ------------------------------------------------------------------
10 # vim:ft=apparmor
11
12 # @{DOVECOT_MAILSTORE} is a space-separated list of all directories
13 # where dovecot is allowed to store and read mails
14 #
15 # The default value is quite broad to avoid breaking existing setups.
16 # Please change @{DOVECOT_MAILSTORE} to (only) contain the directory
17 # you use, and remove everything else.
18
19 @{DOVECOT_MAILSTORE}=@{HOME}/Maildir/ @{HOME}/mail/ @{HOME}/Mail/ /var/vmail/ /var/mail/ /var/spool/mail/
20
21 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2006-2009 Novell/SUSE
4 # Copyright (C) 2010-2014 Canonical Ltd.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License published by the Free Software Foundation.
9 #
10 # ------------------------------------------------------------------
11
12 # All the tunables definitions that should be available to every profile
13 # should be included here
14
15 include <tunables/home>
16 include <tunables/proc>
17 include <tunables/alias>
18 include <tunables/kernelvars>
19 include <tunables/xdg-user-dirs>
20 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2006-2009 Novell/SUSE
4 # Copyright (C) 2010 Canonical Ltd.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License published by the Free Software Foundation.
9 #
10 # ------------------------------------------------------------------
11
12 # @{HOME} is a space-separated list of all user home directories. While
13 # it doesn't refer to a specific home directory (AppArmor doesn't
14 # enforce discretionary access controls) it can be used as if it did
15 # refer to a specific home directory
16 @{HOME}=@{HOMEDIRS}/*/ /root/
17
18 # @{HOMEDIRS} is a space-separated list of where user home directories
19 # are stored, for programs that must enumerate all home directories on a
20 # system.
21 @{HOMEDIRS}=/home/
22
23 # Also, include files in tunables/home.d for site-specific adjustments to
24 # @{HOMEDIRS}.
25 include <tunables/home.d>
26 ''
0 { pkgs, ... }: ''
1 # "dotfiles" git repo
2 @{HOME_GIT}=@{HOME}/hatch/cFG/
3
4 # Have ~/bin path symlinked to a git repo, hence the abstraction
5 @{HOME_BIN}=@{HOME}/bin/ @{HOME_GIT}/bin/
6
7 # "system-wide configs" git repo
8 @{SYS_GIT}=/etc/core/
9 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2010 Canonical Ltd.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of version 2 of the GNU General Public
6 # License published by the Free Software Foundation.
7 #
8 # ------------------------------------------------------------------
9
10 # The following is a space-separated list of where additional user home
11 # directories are stored, each must have a trailing '/'. Directories added
12 # here are appended to @{HOMEDIRS}. See tunables/home for details. Eg:
13 #@{HOMEDIRS}+=/srv/nfs/home/ /mnt/home/
14 ''
0 { pkgs, ... }: ''
1 # Copyright (C) 2012 Canonical Ltd.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of version 2 of the GNU General Public
5 # License published by the Free Software Foundation.
6 #
7 # ------------------------------------------------------------------
8
9 # This file should contain declarations to kernel vars or variables
10 # that will become kernel vars at some point
11
12 # until kernel vars are implemented
13 # and until the parser supports nested groupings like
14 # @{pid}=[1-9]{[0-9]{[0-9]{[0-9]{[0-9]{[0-9],},},},},}
15 # use
16 @{pid}={[1-9],[1-9][0-9],[1-9][0-9][0-9],[1-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9][0-9]}
17
18 #same pattern as @{pid} for now
19 @{tid}=@{pid}
20
21 #A pattern for pids that can appear
22 @{pids}=@{pid}
23 ''
0 { pkgs, ... }: ''
1 # Last Modified: Thu Aug 2 14:37:03 2007
2 # ------------------------------------------------------------------
3 #
4 # Copyright (C) 2002-2005 Novell/SUSE
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License published by the Free Software Foundation.
9 #
10 # ------------------------------------------------------------------
11
12 #Add your ntpd devices here eg. if you have a DCF clock
13 # @{NTPD_DEVICE}=/dev/ttyS*
14 @{NTPD_DEVICE}="/dev/tty10"
15 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2006 Novell/SUSE
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of version 2 of the GNU General Public
7 # License published by the Free Software Foundation.
8 #
9 # ------------------------------------------------------------------
10
11 # @{PROC} is the location where procfs is mounted.
12 @{PROC}=/proc/
13 ''
0 { pkgs, ... }: ''
1 # Copyright (C) 2012 Canonical Ltd.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of version 2 of the GNU General Public
5 # License published by the Free Software Foundation.
6 #
7 # ------------------------------------------------------------------
8
9 include <tunables/sys>
10
11 # @{securityfs} is the location where securityfs is mounted.
12 @{securityfs}=@{sys}/kernel/security/
13 ''
0 { pkgs, ... }: ''
1 # Copyright (C) 2012 Canonical Ltd.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of version 2 of the GNU General Public
5 # License published by the Free Software Foundation.
6 #
7 # ------------------------------------------------------------------
8
9 # @{sys} is the location where sysfs is mounted.
10 @{sys}=/sys/
11 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2014 Canonical Ltd.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of version 2 of the GNU General Public
7 # License published by the Free Software Foundation.
8 #
9 # ------------------------------------------------------------------
10
11 # Define the common set of XDG user directories (usually defined in
12 # /etc/xdg/user-dirs.defaults)
13 @{XDG_DESKTOP_DIR}="Desktop"
14 @{XDG_DOWNLOAD_DIR}="Downloads"
15 @{XDG_TEMPLATES_DIR}="Templates"
16 @{XDG_PUBLICSHARE_DIR}="Public"
17 @{XDG_DOCUMENTS_DIR}="Documents"
18 @{XDG_MUSIC_DIR}="Music"
19 @{XDG_PICTURES_DIR}="Pictures"
20 @{XDG_VIDEOS_DIR}="Videos"
21
22 # Also, include files in tunables/xdg-user-dirs.d for site-specific adjustments
23 # to the various XDG directories
24 include <tunables/xdg-user-dirs.d>
25 ''
0 { pkgs, ... }: ''
1 # ------------------------------------------------------------------
2 #
3 # Copyright (C) 2014 Canonical Ltd.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of version 2 of the GNU General Public
6 # License published by the Free Software Foundation.
7 #
8 # ------------------------------------------------------------------
9
10 # The following may be used to add additional entries such as for
11 # translations. See tunables/xdg-user-dirs for details. Eg:
12 #@{XDG_MUSIC_DIR}+="Musique"
13
14 #@{XDG_DESKTOP_DIR}+=""
15 #@{XDG_DOWNLOAD_DIR}+=""
16 #@{XDG_TEMPLATES_DIR}+=""
17 #@{XDG_PUBLICSHARE_DIR}+=""
18 #@{XDG_DOCUMENTS_DIR}+=""
19 #@{XDG_MUSIC_DIR}+=""
20 #@{XDG_PICTURES_DIR}+=""
21 #@{XDG_VIDEOS_DIR}+=""
22 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /opt/Upwork/upwork {
4
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
6 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
7 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
8 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
9 include <abstractions/freedesktop>
10 include <abstractions/ssl-certs>
11 include <abstractions/user-tmp>
12 include <abstractions/pulse>
13 include <abstractions/site/base>
14 include <abstractions/site/de>
15
16 owner @{HOME}/.{,config/,cache/}Upwork/ rwkm,
17 owner @{HOME}/.{,config/,cache/}Upwork/** rwkm,
18
19 /etc/ r,
20 /etc/*-release r,
21
22 /opt/Upwork/upwork ix,
23 /opt/Upwork/ r,
24 /opt/Upwork/** rm,
25
26 owner @{HOME}/.pki{,/nssdb}/ rw,
27 owner @{HOME}/.pki/nssdb/** rwmk,
28 audit deny @{HOME}/.pki/nssdb/*.so{,.[0-9]*} wl,
29
30 deny @{HOME}/.config/autostart/ rw,
31 deny @{HOME}/.mozilla/ rw,
32 deny @{HOME}/.mozilla/** rw,
33
34 # What it tries to do with bash [5.1.0.562]:
35 # fingerprint platform: /bin/sh -c dmidecode -t ...
36 # check for vm: /bin/sh -c dmesg | grep -i virtual | grep -iE "vmware|qemu|kvm|xen"
37 deny /usr/bin/bash x,
38
39 deny /opt/Upwork/cmon x, # crash monitor binary
40 deny /dev/video0 rwk, # don't need that
41
42 # Tries to ptrace itself for some reason (integrity check?)
43 allow capability sys_ptrace,
44 deny ptrace,
45 deny @{PROC}/sys/kernel/yama/ptrace_scope r,
46
47 # Not sure what happens here, maybe signal to missing pid?
48 deny signal (send) peer=unconfined,
49
50 # Common noise when running from console
51 deny /dev/tty rw,
52 deny /sys/devices/virtual/tty/tty*/active rw,
53 deny /dev/pts/* rw,
54
55 @{PROC} r,
56 owner @{PROC}/@{pid}/fd/ r,
57 owner @{PROC}/@{pid}/task/@{pid}/status r,
58 owner @{PROC}/@{pid}/mountinfo r,
59 owner @{PROC}/@{pid}/task/ r,
60 owner @{PROC}/@{pid}/task/[0-9]*/stat r,
61 owner @{PROC}/@{pid}/environ r,
62 owner @{PROC}/@{pid}/oom_score_adj rw,
63
64 @{PROC}/sys/kernel/shmmax r,
65 @{PROC}/sys/fs/inotify/max_user_watches r,
66
67 deny @{PROC}/*/stat{,m} r,
68 deny @{PROC}/{uptime,vmstat} r,
69 deny @{PROC}/*/comm r,
70
71 /dev/ r,
72 /sys/bus/pci/devices/ r,
73 /sys/devices/pci** r,
74 /etc/udev/udev.conf r,
75 /run/udev/queue.bin r,
76 /run/udev/data/* r,
77
78 /tmp/.org.chromium.Chromium.*/ rw,
79 /tmp/.org.chromium.Chromium.*/** rwmk,
80 /dev/shm/.org.chromium.Chromium.* rwkm,
81 /dev/shm/org.chromium.Chromium.shmem.* rwmk,
82
83 network,
84
85 }
86 ''
0 { pkgs, ... }: ''
1 # For waterfox-current
2 # See also https://github.com/mk-fg/waterfox
3
4 include <tunables/global>
5
6 profile /opt/waterfox-current/waterfox-current {
7 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
8 include <abstractions/site/base>
9 include <abstractions/site/de>
10 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
11 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
12 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
13 include <abstractions/freedesktop>
14 include <abstractions/ssl-certs>
15 include <abstractions/pulse>
16 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dconf"
17 include <abstractions/user-download>
18
19 /opt/waterfox-current/waterfox-current cix, # tabs
20 @{HOME}/.waterfox/url-handler cUx, # dispatcher for magnet: and such
21
22 /opt/waterfox-current/** rm,
23
24 /etc/mime.types r,
25 /usr/share/glib-2.0/schemas/gschemas.compiled r,
26 /usr/share/applications/screensavers/ r,
27
28 deny capability sys_admin,
29 deny capability sys_chroot,
30 deny capability sys_ptrace,
31
32 signal (receive) peer=unconfined,
33 deny signal (send) peer=unconfined,
34
35 owner @{HOME}/.waterfox/ rwk,
36 owner @{HOME}/.waterfox/** rwkm,
37
38 deny @{HOME}/.mozilla/ rw,
39 deny @{HOME}/.mozilla/** rw,
40
41 owner @{HOME}/.cache/waterfox/ rwk,
42 owner @{HOME}/.cache/waterfox/** rwkm,
43 owner @{HOME}/.cache/mesa_shader_cache/** rwk,
44
45 owner @{PROC}/@{pid}/fd/ r,
46 owner @{PROC}/@{pid}/{mountinfo,statm,smaps} r,
47 owner @{PROC}/@{pid}/task/@{pids}/stat r,
48 @{PROC}/@{pids}/net/arp r,
49 @{PROC}/@{pids}/{uid_map,gid_map,setgroups} rw,
50
51 owner /run/user/[0-9]*/dconf/user rw,
52
53 /dev/ r,
54 /dev/shm/org.chromium.* rwkm,
55 /dev/shm/org.mozilla.ipc.* rwkm,
56
57 # Must use TMPDIR=/tmp/waterfox/ env to have it store all its stuff there
58 # Otherwise it creates a lot of different non-descriptive files/dirs in /tmp root
59 /tmp/waterfox/ rwk,
60 /tmp/waterfox/** rwk,
61
62 # GPU identification
63 /sys/bus/pci/devices/ r,
64 /sys/devices/pci[0-9:.]*/[0-9:.]*/* r,
65 /sys/devices/pci[0-9:.]*/[0-9:.]*/[0-9:.]*/* r,
66
67 # U2F token, can be tested via https://webauthn.io/
68 /sys/devices/system/cpu/present r,
69 /run/udev/data/* r,
70 /sys/devices/pci*/ r,
71 /sys/devices/pci*/*/ r,
72 /sys/devices/pci*/*/usb*/ r,
73 /sys/devices/pci*/*/usb*/**/uevent r,
74 /sys/{bus,class,class/hidraw}/ r,
75 /sys/class/hidraw/hidraw* r,
76 /dev/hidraw* rw,
77
78 # File selection dialogs
79 deny @{HOME} r,
80 /etc/fstab r,
81 /run/mount/utab r,
82
83 # All network
84 network inet dgram,
85 network inet stream,
86 }
87 ''
0 { pkgs, ... }: ''
1 include <tunables/global>
2
3 /usr/bin/wine-preloader {
4
5 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
6 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
7 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
8 include <abstractions/site/de>
9 include <abstractions/site/base>
10 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
11 include <abstractions/freedesktop>
12 include <abstractions/pulse>
13 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/p11-kit"
14
15 /usr/bin/wine-preloader rix,
16 /usr/bin/wineserver px,
17 /usr/bin/wine mr,
18
19 /usr/lib/wine/*.so mr,
20 /usr/share/wine/fonts/ r,
21 /usr/share/wine/fonts/* r,
22 /usr/share/wine/wine.inf r,
23
24 /etc/fstab r,
25 /usr/share/terminfo/** r,
26
27 /tmp/.wine-*/ rw,
28 /tmp/.wine-*/server-*/ rw,
29 /tmp/.wine-*/server-*/* rwmk,
30
31 owner @{HOME}/ r,
32 owner @{HOME}/.wine/ rw,
33 owner @{HOME}/.wine/** rwmk,
34 owner @{HOME}/.local/share/icons/hicolor/** rwk,
35 owner @{HOME}/.local/share/applications/** rwk,
36 owner @{HOME}/.config/menus/applications-merged/wine-* rwk,
37 owner @{HOME}/.local/share/desktop-directories/wine-* rwk,
38
39 # Mostly winemenubuilder stuff
40 deny /usr/bin/update-mime-database x,
41 deny /usr/bin/update-desktop-database x,
42 deny @{HOME}/.local/share/mime/** w,
43
44 # For winedbg
45 deny capability sys_ptrace,
46 # owner @{PROC}/*/mem rw,
47
48 # hw
49 /etc/udev/udev.conf r,
50 /run/udev/data/* r,
51 /run/udev/queue.bin r,
52 /sys/devices/pci** r,
53 /dev/video0 rw, # dri?
54
55 # for initial ~/.wine creation/updates only
56 / r,
57 /usr/share/wine/** r,
58 owner @{HOME}/.cache/ r,
59 owner @{HOME}/.cache/wine/ rwk,
60 owner @{HOME}/.cache/wine/** rwk,
61
62 # Actual apps/games
63 owner @{PROC}/@{pid}/mounts r,
64 /etc/machine-id r,
65 /mnt/iso/ r,
66 /mnt/iso/** r,
67 deny @{HOME}/Downloads/ rw,
68 deny @{HOME}/Downloads/** rw,
69 deny @{HOME}/.local/share/Trash/ rw,
70
71 /usr/bin/dosbox cx -> dosbox,
72
73 profile dosbox {
74 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
75 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
76 include <abstractions/pulse>
77 include <abstractions/site/base>
78
79 /etc/fstab r,
80 owner @{PROC}/@{pid}/mounts r,
81
82 # DosBox seem to use these directly
83 /dev/input/event[0-9]* r,
84 /dev/input/js[0-9]* r,
85
86 owner @{HOME}/ r,
87 owner @{HOME}/.wine/ rw,
88 owner @{HOME}/.wine/** rwmk,
89
90 # Actual apps/games
91 /mnt/iso/ r,
92 /mnt/iso/** r,
93 }
94
95 }
96
97 /usr/bin/wineserver {
98
99 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
100 include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
101 include <abstractions/freedesktop>
102
103 /usr/bin/wineserver r,
104
105 /tmp/.wine-*/ rw,
106 /tmp/.wine-*/server-*/ rw,
107 /tmp/.wine-*/server-*/* rwmk,
108
109 owner @{HOME}/ r,
110 owner @{HOME}/.wine/ rw,
111 owner @{HOME}/.wine/** rwmk,
112 owner @{HOME}/.local/share/icons/hicolor/** rwk,
113
114 # For winedbg
115 deny capability sys_ptrace,
116 # owner @{PROC}/*/mem rw,
117
118 # for initial ~/.wine creation only
119 / r,
120 /usr/share/wine/** rk,
121 owner @{HOME}/.cache/ r,
122 owner @{HOME}/.cache/wine/ rwk,
123 owner @{HOME}/.cache/wine/** rwk,
124
125 # Actual apps/games
126 network ipx dgram, # IPX, wow ;)
127 /etc/machine-id r,
128 /etc/ld.so.preload r,
129 /mnt/iso/ r,
130 /mnt/iso/** r,
131 deny @{HOME}/Downloads/ rw,
132 deny @{HOME}/.local/share/Trash/ rw,
133
134 }
135 ''
0 { config, pkgs, lib, ... }:
1
2 let
3 hostAddress = "10.9.0.1";
4 localAddress = "10.9.0.2";
5 in {
6 containers.anki =
7 {
8 autoStart = true;
9 enableTun = true;
10 privateNetwork = true;
11 inherit hostAddress localAddress;
12
13 config =
14 { config, stdenv, ... }:
15
16 {
17 nixpkgs.pkgs = pkgs;
18
19 environment.systemPackages = with pkgs; [
20 ankisyncd
21 ];
22
23 services.ankisyncd = {
24 enable = true;
25 host = localAddress;
26 openFirewall = false;
27 port = 27701;
28 };
29 };
30 };
31 }
0 { config, pkgs, ... }:
1
2 {
3 environment.systemPackages = with pkgs; [ step-cli ];
4
5 containers.authority = {
6 autoStart = true;
7 enableTun = true;
8 privateNetwork = true;
9 hostAddress = "10.4.0.1";
10 localAddress = "10.4.0.2";
11 config =
12 { config, ... }:
13 {
14 environment.systemPackages = with pkgs; [ step-cli step-ca ];
15
16 systemd.services.step-ca = {
17 description = "Step CA Daemon";
18 script = with pkgs; ''${systemd}/bin/systemd-ask-password --timeout=3600 --no-tty 'CA Password:' | ${step-ca}/bin/step-ca config/ca.json --password-file /dev/stdin'';
19 serviceConfig = {
20 WorkingDirectory = "/var/lib/step/";
21 Restart = "always";
22 };
23 wantedBy = [ "multi-user.target" ];
24 };
25
26 networking.firewall.enable = false;
27 };
28 bindMounts = {
29 "/var/lib/step" = {
30 hostPath = "/var/lib/step";
31 isReadOnly = false;
32 };
33 "/run/systemd/ask-password" = {
34 hostPath = "/run/systemd/ask-password";
35 isReadOnly = false;
36 };
37 "/run/systemd/ask-password-block" = {
38 hostPath = "/run/systemd/ask-password-block";
39 isReadOnly = false;
40 };
41 };
42 };
43 }
0 { config, pkgs, lib, ... }:
1
2 {
3 options.ssl.servers = lib.mkOption {
4 type = with lib.types; listOf string;
5 default = [
6 "sso.${domains.home}"
7 "torrent.${domains.home}"
8 "search.${domains.home}"
9 "ca.${domains.home}"
10 domains.srvc
11 "u.${domains.srvc}"
12 "ublog.${domains.srvc}"
13 "microblog.${domains.srvc}"
14 "mastodon.${domains.srvc}"
15 "matrix.${domains.srvc}"
16 ];
17 };
18 config = {
19 security.acme.certs = let
20 mkCert = host: {
21 name = host;
22 value = {
23 allowKeysForGroup = true;
24 #directory = "/var/lib/acme/${host}/";
25 #domain = host;
26 email = "ssl@${domains.home}";
27 extraDomains = { "www.${host}" = null; };
28 group = "keys";
29 #plugins = [ "fullchain.pem" "full.pem" "key.pem" "account_key.json" "account_reg.json" ]
30 ## "cert.der", "cert.pem", "chain.pem", "external.sh", "key.der"
31 postRun = "systemctl restart traefik";
32 webroot = "/var/www/${host}/";
33 };
34 };
35 in builtins.listToAttrs (map mkCert config.ssl.servers);
36
37 systemd.services.haproxy.serviceConfig = lib.mkIf config.services.haproxy.enable {
38 SupplementaryGroups = "keys";
39 };
40
41 containers.certmon = {
42 autoStart = true;
43 enableTun = true;
44 privateNetwork = true;
45 hostAddress = "10.3.0.1";
46 localAddress = "10.3.0.2";
47 config =
48 { config, ... }:
49 {
50 services.nginx = {
51 enable = true;
52 group = "root";
53 virtualHosts = let
54 mkHost = host: {
55 name = host;
56 value = {
57 serverName = host;
58 serverAliases = [ "www.${host}" ];
59 root = "/var/www/${host}/";
60 };
61 };
62 in builtins.listToAttrs (map mkHost config.ssl.servers);
63 };
64
65 networking.firewall.enable = false;
66 };
67 bindMounts = {
68 "/var/www" = {
69 hostPath = "/var/www";
70 isReadOnly = true;
71 };
72 };
73 };
74 };
75 }
0 { config, pkgs, lib, usr, ... }:
1
2 let
3 hostAddress = "10.8.0.1";
4 localAddress = "10.8.0.2";
5 in {
6 containers.hydroxide =
7 {
8 autoStart = true;
9 enableTun = true;
10 privateNetwork = true;
11 inherit hostAddress localAddress;
12
13 config =
14 { config, stdenv, ... }:
15
16 {
17 _module.args = { inherit usr; };
18
19 imports = [
20 ../modules/services/hydroxide
21 ../profiles/services/hydroxide
22 ];
23
24 nixpkgs.pkgs = pkgs;
25
26 environment.systemPackages = with pkgs; [
27 hydroxide
28 ];
29
30 services.hydroxide.host = localAddress;
31 };
32 };
33 }
0 { config, pkgs, lib, domains, ... }:
1
2 let
3 hostAddress = "10.11.0.1";
4 localAddress = "10.11.0.2";
5
6 hostConfig = config;
7 in {
8 containers.jellyfin =
9 {
10 autoStart = true;
11 enableTun = true;
12 privateNetwork = true;
13 inherit hostAddress localAddress;
14
15 config =
16 { config, stdenv, ... }:
17
18 {
19 config = {
20 nixpkgs.pkgs = pkgs;
21
22 networking.firewall.enable = false;
23
24 environment.systemPackages = with pkgs; [
25 yq yj jq git vim tree
26 ];
27
28 services.jellyfin.enable = true;
29
30 services.sonarr.enable = true;
31 services.radarr.enable = true;
32 services.lidarr.enable = true;
33 services.bazarr.enable = true;
34 services.jackett.enable = true;
35
36 services.transmission = {
37 enable = true;
38 settings.dht-enabled = true;
39 settings.download-dir = "/srv/ftp/";
40 settings.download-queue-enabled = false;
41 settings.peer-port = 51413;
42 settings.rpc-authentication-required = false;
43 settings.rpc-bind-address = "0.0.0.0";
44 settings.rpc-host-whitelist-enabled = false;
45 settings.rpc-whitelist-enabled = false;
46 };
47 systemd.services.transmission = {
48 environment.TRANSMISSION_WEB_HOME = pkgs.fetchFromGitHub {
49 owner = "Secretmapper";
50 repo = "combustion";
51 rev = "d5ff91d4078b41bd3738542a20d802cd3ff6cc1e";
52 sha256 = "gZ4YOKMsnYEWDLnh8OZNwEg1ZJioZsWrOcAjHLIyFYg=";
53 };
54 };
55
56 users = rec {
57 users = {
58 root.extraGroups = [ "transmission" ];
59
60 jellyfin.extraGroups = [ "transmission" ];
61 sonarr.extraGroups = [ "transmission" ];
62 radarr.extraGroups = [ "transmission" ];
63 lidarr.extraGroups = [ "transmission" ];
64 bazarr.extraGroups = [ "transmission" ];
65 jackett.extraGroups = [ "transmission" ];
66
67 transmission = lib.mapAttrs (_: lib.mkForce) {
68 inherit (hostConfig.users.users.bao) uid group;
69 } // {
70 isNormalUser = true;
71 extraGroups = [ "transmission" ];
72 };
73 };
74 };
75 };
76 };
77 bindMounts = {
78 "/srv/ftp/tv" = {
79 hostPath = "/srv/ftp/tv/";
80 isReadOnly = false;
81 };
82 "/srv/ftp/TV" = {
83 hostPath = "/srv/ftp/tv/";
84 isReadOnly = false;
85 };
86 "/srv/ftp/movies" = {
87 hostPath = "/srv/ftp/movies/";
88 isReadOnly = false;
89 };
90 "/srv/ftp/Movies" = {
91 hostPath = "/srv/ftp/movies/";
92 isReadOnly = false;
93 };
94 "/srv/ftp/music" = {
95 hostPath = "/srv/ftp/music/";
96 isReadOnly = false;
97 };
98 "/srv/ftp/Music" = {
99 hostPath = "/srv/ftp/music/";
100 isReadOnly = false;
101 };
102 "/srv/ftp/books" = {
103 hostPath = "/srv/ftp/books/";
104 isReadOnly = false;
105 };
106 "/srv/ftp/Books" = {
107 hostPath = "/srv/ftp/books/";
108 isReadOnly = false;
109 };
110 "/srv/ftp/torrents" = {
111 hostPath = "/srv/ftp/";
112 isReadOnly = false;
113 };
114 "/srv/ftp/Torrents" = {
115 hostPath = "/srv/ftp/";
116 isReadOnly = false;
117 };
118 };
119 };
120
121 system.activationScripts.srv-ftp = ''
122 mkdir -p /srv/ftp
123 chmod g+rwx /srv/ftp
124 '';
125
126 systemd.tmpfiles.rules = [
127 "d /srv/ftp 2777 root root"
128 ];
129 }
0 { config, pkgs, lib, domains, ... }:
1
2 let
3 klaus = pkgs.klaus.overrideAttrs (v: {
4 propagatedBuildInputs = v.propagatedBuildInputs ++ [
5 pkgs.python3.pkgs.python-ctags3
6 ];
7 });
8 in {
9 environment.systemPackages = [
10 klaus
11 ];
12
13 isolation.scopes.klaus = {
14 nixos = { ... }: {
15 networking.firewall.enable = false;
16
17 environment.systemPackages = (with pkgs; [
18 yq yj jq git darcs pijul subversion mercurial
19 ]) ++ [ klaus ];
20
21 systemd.services.klaus = {
22 path = [ pkgs.git pkgs.ctags ];
23 environment = {
24 PORT = "3000";
25 HOST = "0.0.0.0";
26 DOMAIN = "dev.${domains.home}";
27 CTAGS = "tags-and-branches";
28 PATHS = lib.concatMapStringsSep " " (n: "/srv/${n}") [
29 "nixrc"
30 ];
31 };
32 serviceConfig = {
33 ExecStart = "${klaus}/bin/klaus --host $HOST --port $PORT --site-name $DOMAIN --ctags $CTAGS --smarthttp $PATHS";
34 };
35 wantedBy = [ "default.target" ];
36 };
37 };
38 };
39
40 containers.klaus = {
41 bindMounts = {
42 "/srv" = {
43 hostPath = "/srv/git";
44 isReadOnly = false;
45 };
46 "/etc/ssh" = {
47 hostPath = "/etc/ssh";
48 isReadOnly = true;
49 };
50 };
51 };
52
53 systemd.tmpfiles.rules = [
54 "d /srv/git 1777 root root -"
55 ];
56 }
0 { config, pkgs, lib, usr, ... }:
1
2 let
3 cfg = config.containers.mastodon.config.services.mastodon;
4 securityLimits = config.environment.etc.limits;
5 hostAddress = "10.6.0.1";
6 localAddress = "10.6.0.2";
7 in {
8 services.postgresql.enable = true;
9 services.postgresql.ensureUsers = [
10 {
11 name = cfg.database.user;
12 ensurePermissions."DATABASE ${cfg.database.name}" = "ALL PRIVILEGES";
13 }
14 ];
15 services.postgresql.ensureDatabases = [ cfg.database.name ];
16
17 security.acme.acceptTerms = true;
18
19 containers.mastodon =
20 {
21 autoStart = true;
22 enableTun = true;
23 privateNetwork = true;
24 inherit hostAddress localAddress;
25
26 config =
27 { config, stdenv, ... }:
28
29 {
30 nixpkgs.pkgs = pkgs;
31 nixpkgs.config.allowUnfree = true;
32
33 environment.etc.limits = securityLimits;
34 environment.systemPackages = with pkgs; [
35 postgresql redis postfix config.services.mastodon.package vim wget
36 ];
37
38 services.elasticsearch.enable = true;
39 services.mastodon.enable = true;
40 services.mastodon.automaticMigrations = false;
41 services.mastodon.extraConfig = {
42 EMAIL_DOMAIN_WHITELIST = lib.concatStringsSep "|" [
43 usr.secrets.domains.home
44 #usr.secrets.domains.wife
45 ];
46 ALTERNATE_DOMAINS = lib.concatStringsSep "," [
47 "mastodon.${usr.secrets.domains.srvc}"
48 "microblog.${usr.secrets.domains.srvc}"
49 "ublog.${usr.secrets.domains.srvc}"
50 ];
51 WEB_DOMAIN = "u.${usr.secrets.domains.srvc}";
52 };
53 services.mastodon.localDomain = usr.secrets.domains.srvc;
54 services.mastodon.redis = {
55 createLocally = true;
56 };
57 services.mastodon.database = {
58 createLocally = false;
59 host = hostAddress;
60 };
61 services.mastodon.smtp = {
62 createLocally = true;
63 fromAddress = "mastodon@${usr.secrets.domains.srvc}";
64 user = "mastodon";
65 };
66 services.mastodon.configureNginx = true;
67 services.mastodon.package = pkgs.mastodon;
68 services.postfix.submissionOptions = {
69 mynetworks = "127.0.0.0/8 10.0.0.0/8";
70 };
71 services.nginx = {
72 enable = true;
73 enableReload = true;
74 virtualHosts."${usr.secrets.domains.srvc}" = {
75 #enableACME = lib.mkForce false;
76 serverAliases = [
77 "u.${usr.secrets.domains.srvc}"
78 usr.secrets.domains.srvc
79 "localhost"
80 "127.0.0.1"
81 localAddress
82 ];
83 listen = [
84 { addr = "0.0.0.0"; port = 80; }
85 { addr = "0.0.0.0"; port = 8443; ssl = true; }
86 ];
87 };
88 };
89
90 networking.firewall.enable = false;
91 networking.nameservers = [ "62.210.16.6" "62.210.16.7" ];
92 networking.extraHosts = ''${localAddress}'';
93
94 security.acme.acceptTerms = true;
95 security.acme.email = "ssl@${usr.secrets.domains.home}";
96 };
97 bindMounts = {
98 "/var/lib/mastodon" = {
99 hostPath = "/var/lib/mastodon";
100 isReadOnly = false;
101 };
102 "/var/lib/elasticsearch" = {
103 hostPath = "/var/lib/elasticsearch";
104 isReadOnly = false;
105 };
106 };
107 };
108 }
0 { config, pkgs, ... }:
1
2 {
3 systemd.nspawn.sandbox = {
4 aliases = [ "sandbox" ];
5 execConfig = {
6 Boot = true;
7 };
8 filesConfig = {
9 BindReadOnly = [
10 "/home:/var/home/lower"
11 "/etc/sandbox/fstab:/etc/fstab"
12 "/etc/sandbox/hostname:/etc/hostname"
13 ];
14 Bind = [ "/srv" ];
15 };
16 networkConfig = {
17 VirtualEthernet = true;
18 };
19 wantedBy = [
20 "multi-user.target"
21 ];
22 requiredBy = [
23 "network-link-ve-sandbox.service"
24 ];
25 };
26 systemd.units."network-link-ve-sandbox.service".requiredBy = [
27 "systemd-nspawn@sandbox.service"
28 ];
29 networking.interfaces.ve-sandbox = {
30 useDHCP = true;
31 ipv4 = {
32 addresses = [
33 { address = "10.1.0.1"; prefixLength = 32; }
34 ];
35 routes = [
36 { address = "10.1.0.2"; prefixLength = 32; options = { src = "10.1.0.1"; }; }
37 ];
38 };
39 };
40 environment.etc.sandbox-fstab = {
41 target = "sandbox/fstab";
42 text = ''
43 # <file system> <dir> <type> <options> <dump> <pass>
44 tmpfs /var/home tmpfs rw,nosuid,noatime,size=512m 0 0
45 overlayfs /home overlay rw,lowerdir=/var/home/lower,upperdir=/var/home/upper,workdir=/var/home/work 0 0
46 /srv/sync/Sources /usr/local/src none rw,bind 0 0
47 '';
48 };
49 }
0 { config, pkgs, ... }:
1
2 {
3 containers.search =
4 {
5 autoStart = true;
6 enableTun = true;
7 privateNetwork = true;
8 hostAddress = "10.5.0.1";
9 localAddress = "10.5.0.2";
10 config =
11 { config, stdenv, ... }:
12
13 {
14 systemd.services.yacy =
15 with pkgs; {
16 description = "Yacy P2P Search Engine";
17 after = [ "network.target" ];
18 path = [
19 which
20 getopt
21 openjdk
22 ];
23 environment = {
24 YACY_DATA_PATH = "${pkgs.yacy}/yacy";
25 YACY_PARENT_DATA_PATH = "${pkgs.yacy}/yacy";
26 };
27 serviceConfig = {
28 WorkingDirectory = "${pkgs.yacy}/yacy";
29 TimeoutStopSec = "50";
30 RestartSec = "3";
31 };
32 script = "set -x; . ${pkgs.yacy}/yacy/env.sh; ${pkgs.openjdk}/bin/java $JAVA_ARGS -classpath $CLASSPATH net.yacy.yacy";
33 preStop = "set -x; . ${pkgs.yacy}/yacy/env.sh; ${pkgs.openjdk}/bin/java $JAVA_ARGS -cp $CLASSPATH net.yacy.yacy -shutdown";
34 wantedBy = [ "multi-user.target" ];
35 };
36
37 networking.firewall.enable = false;
38 };
39 bindMounts = {
40 "/var/lib/yacy" = {
41 hostPath = "/var/lib/yacy";
42 isReadOnly = false;
43 };
44 };
45 };
46 }
0 { config, pkgs, ... }:
1
2 {
3 containers.secure = {
4 autoStart = true;
5 enableTun = true;
6 privateNetwork = true;
7 hostAddress = "10.2.0.1";
8 localAddress = "10.2.0.2";
9 config =
10 { config, ... }:
11 {
12 };
13 };
14 }
0 { config, pkgs, lib, usr, flake, ... }:
1
2 let
3 hostAddress = "10.7.0.1";
4 localAddress = "10.7.0.2";
5 hostAddress6 = "fec0::ffff:10.7.0.1";
6 localAddress6 = "fec0::ffff:10.7.0.2";
7 in {
8 #services.postgresql = {
9 # enable = true;
10 # ensureUsers = [{
11 # name = "prosody";
12 # ensurePermissions."DATABASE \"prosody\"" = "ALL PRIVILEGES";
13 # }];
14 # ensureDatabases = [ "prosody" ];
15 #};
16
17 containers.xmpp =
18 {
19 autoStart = true;
20 enableTun = true;
21 privateNetwork = true;
22 inherit hostAddress localAddress;
23 inherit hostAddress6 localAddress6;
24
25 config =
26 { ... }:
27
28 {
29 nixpkgs = { inherit pkgs; };
30
31 environment.systemPackages = with pkgs; [ jq vim ipfs ipfscat ];
32 environment.variables = {
33 IPFS_PATH = "${pkgs.runCommand "ipfs-path" {
34 api = "/ip4/${usr.secrets.hosts.wireguard.ipv4.zeta}/tcp/5001";
35 passAsFile = [ "api" ];
36 } ''
37 mkdir $out
38 ln -s $apiPath $out/api
39 ''}";
40 };
41
42 services.prosody = rec {
43 enable = true;
44 admins = [ "qy@${usr.secrets.domains.srvc}" ];
45 allowRegistration = true;
46 extraConfig = ''
47 local_interfaces = { "*", "::" }
48 Component "irc.${usr.secrets.domains.srvc}"
49 component_port = { 5347 }
50 component_secret = "${usr.secrets.weechat.credentials.password}"
51 '';
52 httpPorts = [ 5280 ];
53 httpsPorts = [ 5281 ];
54 group = "keys";
55 modules.admin_adhoc = true;
56 modules.admin_telnet = true;
57 modules.bosh = true;
58 modules.groups = true;
59 modules.legacyauth = true;
60 modules.websocket = true;
61 muc = [{
62 domain = "muc.${usr.secrets.domains.srvc}";
63 maxHistoryMessages = 10000;
64 name = "Zeta Prosody";
65 }];
66 ssl = {
67 cert = "/var/lib/acme/${usr.secrets.domains.srvc}/fullchain.pem";
68 key = "/var/lib/acme/${usr.secrets.domains.srvc}/key.pem";
69 };
70 uploadHttp = {
71 domain = "xmpp.${usr.secrets.domains.srvc}";
72 };
73 #disco_items = [{
74 # url = "xmpp.${usr.secrets.domains.srvc}";
75 #}];
76 virtualHosts.srvc = {
77 enabled = true;
78 domain = usr.secrets.domains.srvc;
79 };
80 };
81
82 networking.firewall.enable = false;
83 };
84 bindMounts = {
85 "/var/lib/prosody" = {
86 hostPath = "/var/lib/prosody";
87 isReadOnly = false;
88 };
89 "/var/lib/acme" = {
90 hostPath = "/var/lib/acme";
91 isReadOnly = true;
92 };
93 };
94 };
95 }
0 { system ? builtins.currentSystem, ... }:
1
2 let
3 lock = builtins.fromJSON (builtins.readFile ./flake.lock);
4 locked-state = lock.nodes.flake-compat.locked;
5 flake-compat = import (fetchTarball (
6 if builtins.pathExists ./flake.lock && builtins.hasAttr "flake-compat" lock.nodes
7 then {
8 url = "https://github.com/edolstra/flake-compat/archive/${locked-state.rev}.tar.gz";
9 hash = locked-state.narHash;
10 }
11 else https://github.com/edolstra/flake-compat/archive/master.tar.gz));
12 flake = flake-compat { src = ./.; };
13 self = if builtins ? getFlake then builtins.getFlake (toString ./.) else flake.defaultNix;
14 hostname = with builtins; head (split "\n" (readFile /etc/hostname));
15 maybe = c: let result = builtins.tryEval c; in if result.success then result.value else {};
16 in rec { inherit flake-compat flake lock; inherit self; inputs = self.passthru.inputs // { inherit self; }; }
17 // maybe self // maybe (self.passthru or {})
18 // maybe self.defaultPackage.${system}
19 // maybe self.defaultPackage.${system}.config.nodes
20 // maybe self.defaultPackage.${system}.config.nodes.${hostname}.configuration
21 // maybe {
22 inherit (self.defaultPackage.${system}.config.nodes.${hostname}.configuration._pkgs) pkgs lib;
23 options = rec {
24 deploy = self.defaultPackage.x86_64-linux.options;
25 nodes = deploy.nodes.type.getSubOptions [];
26 nixos = nodes.configuration.type.getSubOptions [];
27 home = nixos.home-manager.users.type.getSubOptions [];
28 };
29 }
0 nixusArgs: conf: let
1 inherit (nixusArgs) nixpkgs;
2
3 extendLib = super:
4 let
5 lib = super.extend (import ../lib/dag.nix);
6 self = if nixusArgs ? libOverlay
7 then lib.extend nixusArgs.libOverlay
8 else lib;
9 in self;
10
11 nixusPkgs = import nixpkgs {
12 config = {};
13 overlays = [
14 (self: super: { lib = extendLib super.lib; })
15 ];
16 system = nixusArgs.deploySystem or builtins.currentSystem;
17 };
18
19 result = nixusPkgs.lib.evalModules {
20 modules = [
21 modules/options.nix
22 modules/deploy.nix
23 modules/secrets.nix
24 modules/ssh.nix
25 modules/public-ip.nix
26 modules/dns.nix
27 modules/vpn
28 conf
29 # Not naming it pkgs to avoid confusion and trouble for overriding scopes
30 {
31 _module.args.nixus = {
32 pkgs = nixusPkgs;
33 inherit extendLib;
34 };
35 _module.args.pkgs = throw "You're trying to access the pkgs argument from a Nixus module, use the nixus argument instead and use nixus.pkgs from that.";
36 }
37 ];
38 };
39 in result
0 { nixus, lib, config, ... }:
1
2 let
3 inherit (lib) types;
4
5 nodeOptions = node@{ name, pkgs, config, ... }: let
6 switchScript = pkgs.runCommandNoCC "switch" {
7 inherit (config) switchTimeout successTimeout ignoreFailingSystemdUnits privilegeEscalationCommand systemSwitcherDir panicAction rollbackOnFailure;
8 inherit (nixus.pkgs) execline;
9 } ''
10 mkdir -p $out/bin
11 substituteAll ${../scripts/switch.sh} $out/bin/switch
12 chmod +x $out/bin/switch
13 '';
14 in {
15 options = {
16 deployScriptPhases = lib.mkOption {
17 type = types.dagOf types.lines;
18 default = {};
19 };
20
21 deployScriptPath = lib.mkOption {
22 type = types.listOf types.package;
23 default = (with nixus.pkgs; [
24 # Without bash being here deployments to localhost do not work. The
25 # reason for that is not yet known. Reported in #6.
26 bash
27 coreutils
28 execline
29 findutils
30 gnused
31 jq
32 openssh
33 procps
34 rsync
35 ]);
36 };
37
38 dirty = lib.mkOption {
39 type = lib.types.bool;
40 default = false;
41 };
42
43 nodeDeployScript = lib.mkOption {
44 type = types.package;
45 };
46
47 successTimeout = lib.mkOption {
48 type = types.ints.unsigned;
49 default = 20;
50 description = ''
51 How many seconds remote hosts should wait for the success
52 confirmation before rolling back.
53 '';
54 };
55
56 switchTimeout = lib.mkOption {
57 type = types.ints.unsigned;
58 default = 60;
59 description = ''
60 How many seconds remote hosts should wait for the system activation
61 command to finish before considering it failed.
62 '';
63 };
64
65 ignoreFailingSystemdUnits = lib.mkOption {
66 type = types.bool;
67 default = false;
68 description = ''
69 Whether a system activation should be considered successful despite
70 failing systemd units.
71 '';
72 };
73
74 # TODO: What about different ssh ports? Some access abstraction perhaps?
75 host = lib.mkOption {
76 type = lib.types.nullOr lib.types.str;
77 default = name;
78 example = "root@172.18.67.46";
79 description = ''
80 How to reach the host via ssh. Deploying is disabled if null. The
81 username must either be root, or a user that is allowed to do
82 passwordless privilege escalation. If no username is given, the one
83 that runs the deploy script is used.
84 '';
85 };
86
87 hasFastConnection = lib.mkOption {
88 type = lib.types.bool;
89 default = false;
90 description = ''
91 Whether there is a fast connection to this host. If true it will cause
92 all derivations to be copied directly from the deployment host. If
93 false, the substituters are used when possible instead.
94 '';
95 };
96
97 closurePaths = lib.mkOption {
98 type = lib.types.listOf lib.types.package;
99 default = [];
100 description = ''
101 Derivation paths to copy to the host while deploying
102 '';
103 };
104
105 systemSwitcherDir = lib.mkOption {
106 type = lib.types.str;
107 default = "/var/lib/system-switcher/";
108 description = ''
109 Path that will contain the system switcher data
110 '';
111 };
112
113 rollbackOnFailure = lib.mkOption {
114 type = lib.types.bool;
115 default = true;
116 description = ''
117 Whether to rollback if activation signals failure
118 '';
119 };
120
121 panicAction = lib.mkOption {
122 type = lib.types.str;
123 default = "reboot";
124 description = ''
125 Command to run in switcher emergencies
126 '';
127 };
128 };
129
130 config.closurePaths = [
131 config.configuration.system.build.toplevel
132 switchScript
133 nixus.pkgs.execline
134 ];
135
136 config.deployScriptPhases = {
137 copy-closure = lib.dag.entryBefore ["trigger-switch"] ''
138 foreground {
139 fdswap 1 2
140 echo "Copying closure to host..."
141 }
142
143 foreground {
144 define TRIES 3
145 if -n {
146 export NIX_SSHOPTS "-o ServerAliveInterval=15 -o VisualHostKey=no"
147 importas -i host HOST
148 forbacktickx -x 0 tries { seq 1 $TRIES } # TOOD: Prevent garbage collection until the end of the deploy
149 foreground { fdswap 1 2 importas -i try tries echo -en "Attempt ''${try}..." }
150 nix copy --verbose ${lib.optionalString (!config.hasFastConnection) "-s"} --to ssh://$host
151 "${lib.concatStringsSep "\" \"" config.closurePaths}"
152 }
153 echo "Failed to copy closure after ''${TRIES}"
154 }
155 '';
156
157 trigger-switch = lib.dag.entryAnywhere ''
158 foreground {
159 fdswap 1 2
160 echo "Triggering system switcher..."
161 }
162 backtick -i -n ID {
163 importas -i host HOST
164 ssh -o VisualHostKey=no -o BatchMode=yes $host
165 exec "${switchScript}/bin/switch" start "${config.configuration.system.build.toplevel}"
166 }
167 background {
168 importas -i id ID
169 foreground {
170 fdswap 1 2
171 echo "Observing system activation ''${id}..."
172 }
173 importas -i host HOST
174 loopwhilex -x 0
175 ssh -o VisualHostKey=no -o BatchMode=yes $host
176 exec ${builtins.concatStringsSep " " config.privilegeEscalationCommand}
177 cat "${config.systemSwitcherDir}/system-''${id}/fifo"
178 }
179
180 foreground {
181 fdswap 1 2
182 echo "Trying to confirm success..."
183 }
184 if {
185 importas -i id ID
186 importas -i host HOST
187 loopwhilex -x 0,2
188 backtick -i -n STATUS {
189 foreground {
190 # TODO: Because of the imperative network-setup script, when e.g. the
191 # defaultGateway is removed, the previous entry is still persisted on
192 # a rebuild switch, even though with a reboot it wouldn't. Maybe use
193 # the more modern and declarative networkd to get around this
194 timeout --foreground 15
195 ssh -o VisualHostKey=no -o ControlPath=none -o BatchMode=yes $host
196 exec "${switchScript}/bin/switch" active $id
197 }
198 sleep 1
199 }
200
201 fdswap 1 2
202 importas -i status STATUS
203 ifelse { test $status = "success" } {
204 foreground {
205 echo "Successfully activated new system!"
206 } exit 0
207 }
208 ifelse { test $status = "failure" } {
209 foreground {
210 echo "Failed to activate new system! Rolled back to previous one"
211 } exit 2
212 }
213 exit 1
214 }
215 '';
216 };
217
218 config.nodeDeployScript = import ../scripts node;
219 };
220 in {
221 options = {
222 defaults = lib.mkOption {
223 type = lib.types.submodule nodeOptions;
224 };
225
226 deployScript = lib.mkOption {
227 type = lib.types.package;
228 readOnly = true;
229 };
230 };
231
232 # TODO: What about requiring either all nodes to succeed or all get rolled back?
233 config.deployScript = nixus.pkgs.writeScript "deploy" (''
234 #!${nixus.pkgs.execline}/bin/execlineb -Ws0
235 '' + (
236 if lib.any (node: node.dirty) (lib.attrValues config.nodes) then ''
237 foreground { echo Not completing a dirty deployment }
238 exit 41
239 '' else ""
240 ) + ''
241 forx -p script {
242 ${lib.concatMapStringsSep "\n "
243 (node: lib.optionalString node.enabled node.nodeDeployScript)
244 (lib.attrValues config.nodes)}
245 } importas -i script script
246 execlineb $script
247 ''); # TODO: Handle signals to kill the async command
248 }
0 { lib, nixus, config, ... }:
1 let
2 inherit (lib) types;
3
4 cfg = config.dns;
5
6 recordTypes = {
7 A = {
8 options.address = lib.mkOption {
9 type = types.str;
10 };
11 stringCoerce = s: { address = s; };
12 toData = v: v.address;
13 };
14 AAAA = {
15 options.address = lib.mkOption {
16 type = types.str;
17 };
18 stringCoerce = s: { address = s; };
19 toData = v: v.address;
20 };
21 NS = {
22 options.domain = lib.mkOption {
23 type = types.str;
24 };
25 stringCoerce = s: { domain = s; };
26 toData = v: v.domain;
27 };
28 CNAME = {
29 options.domain = lib.mkOption {
30 type = types.str;
31 };
32 stringCoerce = s: { domain = s; };
33 toData = v: v.domain;
34 };
35 CAA = {
36 options.flags.issuerCritical = lib.mkOption {
37 type = types.bool;
38 default = false;
39 };
40 options.tag = lib.mkOption {
41 type = types.enum [ "issue" "issuewild" "iodef" ];
42 };
43 options.value = lib.mkOption {
44 type = types.str;
45 };
46
47 stringCoerce = s: { tag = "issue"; value = s; };
48 toData = v: "${if v.flags.issuerCritical then "128" else "0"} ${v.tag} \"${lib.escape [ "\"" ] v.value}\"";
49 };
50 MX = {
51 options.preference = lib.mkOption {
52 type = types.int;
53 default = 10;
54 };
55
56 options.domain = lib.mkOption {
57 type = types.str;
58 };
59
60 stringCoerce = s: { domain = s; };
61 toData = v: "${toString v.preference} ${v.domain}";
62 };
63 TXT = {
64 options.text = lib.mkOption {
65 type = types.str;
66 };
67
68 stringCoerce = s: { text = s; };
69 toData = v: "\"${lib.escape [ "\"" ] v.text}\"";
70 };
71 SRV = {
72 options.priority = lib.mkOption {
73 type = types.int;
74 default = 0;
75 };
76 options.weight = lib.mkOption {
77 type = types.int;
78 default = 100;
79 };
80 options.port = lib.mkOption {
81 type = types.port;
82 };
83 options.target = lib.mkOption {
84 type = types.str;
85 };
86 toData = v: "${toString v.priority} ${toString v.weight} ${toString v.port} ${v.target}";
87 };
88 };
89
90 /*
91 {
92 "com" = {
93 "infinisil" = {
94 _zone = "infinisil.com";
95 "sub" = {
96 _zone = "sub.infinisil.com";
97 };
98 };
99 };
100 }
101 */
102 zones =
103 let
104 zoneAttr = zone: lib.setAttrByPath (lib.reverseList (lib.splitString "." zone)) { _zone = zone; };
105 result = lib.foldl' (a: e: lib.recursiveUpdate a (zoneAttr e)) {} (lib.attrNames cfg.zones);
106 in result;
107
108 getZone = domain:
109 assert lib.hasSuffix "." domain;
110 let
111 go = zones: path:
112 if path != [] && zones ? ${lib.head path} then go zones.${lib.head path} (lib.tail path)
113 else zones._zone or null;
114 elements = lib.reverseList (lib.init (lib.splitString "." domain));
115 in go zones elements;
116
117 recordSubmodule = { name, ... }: let zone = getZone name; in {
118 options = lib.mapAttrs (_: value:
119 let
120 module = types.submodule ({ options, config, ... }: {
121 options = value.options // {
122 ttl = lib.mkOption {
123 type = types.int;
124 };
125
126 zone = lib.mkOption {
127 type = types.str;
128 };
129 };
130
131 config.zone = lib.mkIf (zone != null) (lib.mkDefault zone);
132 config.ttl = lib.mkIf options.zone.isDefined (lib.mkDefault cfg.zones.${config.zone}.ttl);
133 });
134 type =
135 if value ? stringCoerce then
136 with types; coercedTo (either str attrs) lib.singleton (listOf (coercedTo str value.stringCoerce module))
137 else
138 with types; coercedTo attrs lib.singleton (listOf module);
139 in lib.mkOption {
140 type = type;
141 default = [];
142 }
143 ) recordTypes;
144 };
145
146 recordList = lib.concatLists (lib.mapAttrsToList (name: types:
147 lib.concatLists (lib.mapAttrsToList (type: records:
148 # TODO: Maybe remove duplicates?
149 map (record: {
150 inherit name type;
151 inherit (record) ttl zone;
152 data = recordTypes.${type}.toData record;
153 }) records
154 ) types)
155 ) cfg.records);
156
157 recordsByZone = lib.mapAttrs (_: map (record: removeAttrs record [ "zone" ]))
158 (lib.groupBy (record: record.zone) recordList);
159
160 soaRecord = zoneCfg:
161 let
162 inherit (zoneCfg) soa;
163 serial = if soa.serial == null then "@NIXUS_ZONE_SERIAL@" else toString soa.serial;
164 in {
165 name = zoneCfg.name + ".";
166 type = "SOA";
167 ttl = soa.ttl;
168 # TODO: Email escaping and transforming
169 data = "${soa.master} ${soa.email} ${serial} ${toString soa.refresh} ${toString soa.retry} ${toString soa.expire} ${toString soa.negativeTtl}";
170 };
171
172
173 nodeConfigs = lib.mapAttrs (node: zones: {
174 configuration = {
175 networking.firewall.allowedUDPPorts = [ 53 ];
176 services.bind = {
177 enable = true;
178 zones = map (zone: {
179 name = zone.name;
180 master = true;
181 file = zone.zonefile;
182 }) zones;
183 };
184 };
185
186 }) (lib.groupBy (z: z.primaryNode) (lib.attrValues cfg.zones));
187
188 in {
189
190 # Records that automatically get set to the appropriate zone
191 options.dns.records = lib.mkOption {
192 type = types.attrsOf (types.submodule recordSubmodule);
193 default = {};
194 };
195
196 options.dns.zones = lib.mkOption {
197 default = {};
198 type = types.attrsOf (types.submodule ({ name, config, ... }: {
199 options.name = lib.mkOption {
200 type = types.str;
201 default = name;
202 };
203
204 options.primaryNode = lib.mkOption {
205 type = types.str;
206 description = ''
207 Nixus node for the primary server
208 '';
209 };
210
211 options.ttl = lib.mkOption {
212 type = types.int;
213 description = ''
214 The TTL to use for records in this zone if the records themselves don't specify it.
215 '';
216 };
217
218 options.records = lib.mkOption {
219 type = types.listOf (types.submodule {
220 options.name = lib.mkOption {
221 type = types.str;
222 description = "Record owner name";
223 };
224 options.type = lib.mkOption {
225 type = types.str;
226 description = "Record type";
227 };
228 options.ttl = lib.mkOption {
229 type = types.int;
230 description = "Record TTL";
231 };
232 options.data = lib.mkOption {
233 type = types.str;
234 description = "Record data";
235 };
236 });
237 default = [ (soaRecord config) ] ++ recordsByZone.${config.name};
238 };
239
240 options.zonefile = lib.mkOption {
241 type = types.path;
242 default = nixus.pkgs.runCommand "${config.name}.zone" {
243 contents = lib.concatMapStrings (record:
244 "${record.name} ${toString record.ttl} IN ${record.type} ${record.data}\n"
245 ) config.records;
246 passAsFile = [ "contents" ];
247 } ''
248 substitute "$contentsPath" "$out" --subst-var-by NIXUS_ZONE_SERIAL "$(date +%s)"
249 ${lib.getBin nixus.pkgs.bind}/bin/named-checkzone ${lib.escapeShellArg config.name} "$out"
250 '';
251 };
252
253 options.soa = {
254
255 ttl = lib.mkOption {
256 type = types.int;
257 description = "TTL of the SOA record itself.";
258 };
259
260 master = lib.mkOption {
261 type = types.str;
262 description = "The primary master name server for this zone.";
263 };
264
265 email = lib.mkOption {
266 type = types.str;
267 description = "Email address of the person responsible for this zone.";
268 };
269
270 # TODO: Don't require these 4 fields unless there are secondary servers
271 serial = lib.mkOption {
272 type = types.nullOr types.int;
273 default = null;
274 description = "Serial number for this zone. Should be updated if any records change so that secondary servers are refreshed. Null indicates a serial number automatically generated from the current unix epoch.";
275 };
276
277 refresh = lib.mkOption {
278 type = types.int;
279 description = "Number of seconds after which secondary name servers should query the master for the SOA record, to detect zone changes";
280 };
281
282 retry = lib.mkOption {
283 type = types.int;
284 description = "Number of seconds after which secondary name servers should retry to request the serial number from the master if the master does not respond.";
285 };
286
287 expire = lib.mkOption {
288 type = types.int;
289 description = "Number of seconds after which secondary name servers should stop answering request for this zone if the master does not respond.";
290 };
291
292 negativeTtl = lib.mkOption {
293 type = types.int;
294 description = "How long negative responses should be cached for.";
295 };
296 };
297
298 config.soa.ttl = lib.mkDefault config.ttl;
299 }));
300 };
301
302 config.nodes = nodeConfigs;
303 }
0 { nixus, options, config, lib, ... }:
1 let
2 inherit (lib) types;
3
4 extraConfig = { lib, config, ... }: {
5 systemd.services = lib.mkIf (!config.services.openssh.startWhenNeeded) {
6 # By default the sshd service doesn't stop when changed so you don't lose connection to it when misconfigured
7 # But in Nixus we want to detect a misconfiguration since we can rollback in that case
8 sshd.stopIfChanged = lib.mkForce true;
9 };
10 };
11
12 pkgsModule = nixpkgs: { lib, config, ... }: {
13 config.nixpkgs.system = lib.mkDefault nixus.pkgs.system;
14 # Not using nixpkgs.pkgs because that would apply the overlays again
15 config._module.args.pkgs = lib.mkDefault (import nixpkgs {
16 inherit (config.nixpkgs) config overlays localSystem crossSystem;
17 });
18
19 # Export the pkgs arg because we use it outside the module
20 # See https://github.com/NixOS/nixpkgs/pull/82751 why that's necessary
21 options._pkgs = lib.mkOption {
22 readOnly = true;
23 internal = true;
24 default = config._module.args.pkgs;
25 };
26 };
27
28 topconfig = config;
29
30 nodeOptions = { name, config, ... }: {
31
32 options = {
33
34 enabled = lib.mkOption {
35 type = lib.types.bool;
36 default = true;
37 description = ''
38 Whether this node should be included in the build.
39 '';
40 };
41
42 nixpkgs = lib.mkOption {
43 type = lib.types.path;
44 default = nixus.pkgs.path;
45 example = lib.literalExample ''
46 fetchTarball {
47 url = "https://github.com/NixOS/nixpkgs/tarball/a06925d8c608d7ba1d4297dc996c187c37c6b7e9";
48 sha256 = "0xy6rimd300j5bdqmzizs6l71x1n06pfimbim1952fyjk8a3q4pr";
49 }
50 '';
51 description = ''
52 The path to the nixpkgs version to use for this host.
53 '';
54 };
55
56 configuration = lib.mkOption {
57 type =
58 let baseModules = import (config.nixpkgs + "/nixos/modules/module-list.nix");
59 in types.submoduleWith {
60 specialArgs = {
61 lib = nixus.extendLib (import (config.nixpkgs + "/lib"));
62 # TODO: Move these to not special args
63 nodes = lib.mapAttrs (name: value: value.configuration) topconfig.nodes;
64 inherit name baseModules;
65 modulesPath = config.nixpkgs + "/nixos/modules";
66 };
67 modules = baseModules ++ [ (pkgsModule config.nixpkgs) extraConfig ];
68 };
69 default = {};
70 example = lib.literalExample ''
71 {
72 imports = [ ./hardware-configuration.nix ];
73 boot.loader.grub.device = "/dev/sda";
74 networking.hostName = "test";
75 }
76 '';
77 description = ''
78 The NixOS configuration for this host.
79 '';
80 };
81
82 privilegeEscalationCommand = lib.mkOption {
83 type = types.listOf types.str;
84 default = [ "sudo" ];
85 example = lib.literalExample ''[ "doas" ]'';
86 description = ''
87 The command to use for privilege escalation.
88 '';
89 };
90
91 };
92
93 config = {
94 _module.args.pkgs = config.configuration._pkgs;
95 };
96 };
97
98 in {
99
100 options = {
101 defaults = lib.mkOption {
102 type = lib.types.submodule nodeOptions;
103 example = lib.literalExample ''
104 { name, ... }: {
105 networking.hostName = name;
106 }
107 '';
108 description = ''
109 Configuration to apply to all nodes.
110 '';
111 };
112
113 nodes = lib.mkOption {
114 type = lib.types.attrsOf (lib.types.submodule (options.defaults.type.functor.payload.modules ++ options.defaults.definitions));
115 description = "nodes";
116 };
117
118 };
119 }
0 { lib, ... }:
1 let
2 inherit (lib) types;
3 in {
4
5 options.defaults = lib.mkOption {
6 type = types.submodule {
7 options.configuration = lib.mkOption {
8 type = types.submoduleWith {
9 modules = [({ options, ... }: {
10 options.networking.public = {
11
12 ipv4 = lib.mkOption {
13 type = types.str;
14 description = "Default public IPv4 address.";
15 };
16 hasIpv4 = lib.mkOption {
17 type = types.bool;
18 readOnly = true;
19 default = options.networking.public.ipv4.isDefined;
20 description = "Whether this node has a public ipv4 address.";
21 };
22
23 ipv6 = lib.mkOption {
24 type = types.str;
25 description = "Default public IPv6 address.";
26 };
27 hasIpv6 = lib.mkOption {
28 type = types.bool;
29 readOnly = true;
30 default = options.networking.public.ipv6.isDefined;
31 description = "Whether this node has a public ipv6 address.";
32 };
33
34 };
35 })];
36 };
37 };
38 };
39 };
40
41 }
0 { lib, config, options, ... }:
1 let
2 inherit (lib) types;
3 # Ideas (inspiration nixops):
4 # - Add systemd units for each key
5 # - persistent/non-persistent keys, send keys after reboot
6
7 # Abstract where the secret is gotten from (different hosts, not only localhost, different commands, not just files)
8
9 secretType = pkgs: baseDir: { name, config, ... }: {
10 options = {
11 file = lib.mkOption {
12 type = types.path;
13 apply = indirectSecret pkgs baseDir config name;
14 };
15 # TODO: Ensure user and group exists at eval time
16 user = lib.mkOption {
17 type = types.nullOr types.str;
18 default = null;
19 description = ''
20 The owning user of the secret. If this is set, only that user can
21 access the secret. Mutually exclusive with setting a group.
22 By default, root is the owning user.
23 '';
24 };
25 group = lib.mkOption {
26 type = types.nullOr types.str;
27 default = null;
28 description = ''
29 The owning group of the secret. If this is set, only that group can
30 access the secret. Mutually exclusive with setting a user.
31 By default, root is the owning user.
32 '';
33 };
34 };
35 };
36
37 # Takes a file path and turns it into a derivation
38 indirectSecret = pkgs: baseDir: config: name: file: pkgs.runCommandNoCC "secret-${name}" {
39 # To find out which file to copy. toString to not import the secret into
40 # the store
41 file = toString file;
42
43 # We make this derivation dependent on the secret itself, such that a
44 # change of it causes a rebuild
45 secretHash = builtins.hashFile "sha512" file;
46 } (
47 let
48 validSecret = (config.user == null) || (config.group == null);
49 subdir = if config.group == null
50 then "per-user/${if config.user == null then "root" else config.user}"
51 else "per-group/${config.group}";
52 target = if validSecret
53 then "${baseDir}/active/${subdir}/${name}"
54 else throw "nixus: secret.${name} can't have both a user and a group set";
55 in ''
56 ln -s "${target}" "$out"
57 '');
58
59 # Intersects the closure of a system with a set of secrets
60 requiredSecrets = pkgs: { system, secrets, host, name, ... }: pkgs.stdenv.mkDerivation {
61 name = "${name}-required-secrets";
62
63 __structuredAttrs = true;
64 preferLocalBuild = true;
65
66 exportReferencesGraph.system = system;
67 secrets = lib.mapAttrsToList (name: value: {
68 inherit name;
69 path = value.file;
70 source = value.file.file;
71 hash = value.file.secretHash;
72 user = if value.group == null && value.user == null then "root" else value.user;
73 inherit (value) group;
74 }) secrets;
75
76 PATH = lib.makeBinPath [pkgs.buildPackages.jq];
77
78 builder =
79 let
80 jqFilter = builtins.toFile "jq-filter" ''
81 [.system[].path] as $system
82 | .secrets[]
83 | select(.path == $system[])
84 '';
85 in builtins.toFile "builder" ''
86 source .attrs.sh
87 jq -r -c -f ${jqFilter} .attrs.json > ''${outputs[out]}
88 '';
89 };
90
91 in {
92
93 options.defaults = lib.mkOption {
94 type = types.submodule ({ config, pkgs, ... }: {
95 options.configuration = lib.mkOption {
96 type = types.submoduleWith {
97 modules = [({ config, ... }: {