commit d462d7bb2963e69263b43a5078faa41943425f31 Author: tdback Date: Sun Nov 10 17:54:08 2024 -0500 starting fresh on a self-hosted forge diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5e192fc --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright 2024 Tyler Dunneback + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/containers/freshrss/default.nix b/containers/freshrss/default.nix new file mode 100644 index 0000000..5ee2e1e --- /dev/null +++ b/containers/freshrss/default.nix @@ -0,0 +1,30 @@ +{ ... }: +let + directories = [ + "/opt/freshrss" + ]; + port = "8888"; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.freshrss = { + image = "freshrss/freshrss:latest"; + autoStart = true; + ports = [ + "${port}:80" + ]; + volumes = [ + "/opt/freshrss/data:/var/www/FreshRSS/data" + "/opt/freshrss/extensions:/var/www/FreshRSS/extensions" + ]; + environment = { + TZ = "America/Detroit"; + CRON_MIN = "*/20"; + }; + }; + + services.caddy.virtualHosts."newspaper.tdback.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${port} + ''; +} diff --git a/containers/jellyfin/default.nix b/containers/jellyfin/default.nix new file mode 100644 index 0000000..b8aea0e --- /dev/null +++ b/containers/jellyfin/default.nix @@ -0,0 +1,27 @@ +{ ... }: +let + directories = [ + "/opt/jellyfin" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.jellyfin = { + image = "jellyfin/jellyfin:latest"; + autoStart = true; + user = "994:994"; + ports = [ + "8096:8096/tcp" + ]; + volumes = [ + "/opt/jellyfin/config:/config" + "/opt/jellyfin/cache:/cache" + "/lagoon/media:/media" + ]; + }; + + services.caddy.virtualHosts."jellyfin.tdback.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:8096 + ''; +} diff --git a/containers/kavita/default.nix b/containers/kavita/default.nix new file mode 100644 index 0000000..c72aca6 --- /dev/null +++ b/containers/kavita/default.nix @@ -0,0 +1,28 @@ +{ ... }: +let + directories = [ + "/opt/kavita" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.kavita = { + image = "jvmilazz0/kavita:latest"; + autoStart = true; + ports = [ + "5000:5000" + ]; + volumes = [ + "/opt/kavita/config:/kavita/config" + "/lagoon/media/library/Books:/books" + ]; + environment = { + TZ = "America/Detroit"; + }; + }; + + services.caddy.virtualHosts."library.tdback.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:5000 + ''; +} diff --git a/containers/navidrome/default.nix b/containers/navidrome/default.nix new file mode 100644 index 0000000..af8160c --- /dev/null +++ b/containers/navidrome/default.nix @@ -0,0 +1,31 @@ +{ ... }: +let + directories = [ + "/opt/navidrome" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.navidrome = { + image = "deluan/navidrome:latest"; + autoStart = true; + ports = [ + "4533:4533" + ]; + volumes = [ + "/opt/navidrome/data:/data" + "/lagoon/media/music:/music:ro" + ]; + environment = { + ND_SCANSCHEDULE = "1h"; + ND_LOGLEVEL = "info"; + ND_SESSIONTIMEOUT = "24h"; + ND_ENABLEUSEREDITING = "false"; + }; + }; + + services.caddy.virtualHosts."radio.tdback.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:4533 + ''; +} diff --git a/containers/pihole/default.nix b/containers/pihole/default.nix new file mode 100644 index 0000000..6c8042d --- /dev/null +++ b/containers/pihole/default.nix @@ -0,0 +1,34 @@ +{ ... }: +let + directories = [ + "/opt/pihole/" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.pihole = { + image = "pihole/pihole:latest"; + autoStart = true; + ports = [ + "53:53/udp" + "53:53/tcp" + "80:80/tcp" + ]; + volumes = [ + "/opt/pihole/etc:/etc/pihole" + "/opt/pihole/etc-dnsmasq.d:/etc/dnsmasq.d" + ]; + environment = { + TZ = "America/Detroit"; + WEBPASSWORD = "pihole4ALL!"; + FTLCONF_LOCAL_IPV4 = "10.0.0.202"; + INTERFACE = "eno1"; + }; + extraOptions = [ "--network=host" ]; + }; + + networking.firewall = { + allowedTCPPorts = [ 53 80 ]; + allowedUDPPorts = [ 53 ]; + }; +} diff --git a/containers/pinchflat/default.nix b/containers/pinchflat/default.nix new file mode 100644 index 0000000..9428c32 --- /dev/null +++ b/containers/pinchflat/default.nix @@ -0,0 +1,23 @@ +{ ... }: +let + directories = [ + "/opt/pinchflat" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.pinchflat = { + image = "keglin/pinchflat:latest"; + autoStart = true; + ports = [ + "8945:8945" + ]; + volumes = [ + "/opt/pinchflat:/config" + "/lagoon/media/yt:/downloads" + ]; + environment = { + TZ = "America/Detroit"; + }; + }; +} diff --git a/containers/stirling-pdf/default.nix b/containers/stirling-pdf/default.nix new file mode 100644 index 0000000..904fd6d --- /dev/null +++ b/containers/stirling-pdf/default.nix @@ -0,0 +1,23 @@ +{ ... }: +let + directories = [ + "/opt/stirling" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.pdf-tools = { + image = "frooodle/s-pdf:latest"; + autoStart = true; + ports = [ + "8060:8080" + ]; + volumes = [ + "/opt/stirling/training-data:/usr/share/tesseract-ocr/4.00/tessdata" + "/opt/stirling/configs:/configs" + ]; + environment = { + DOCKER_ENABLE_SECURITY = "false"; + }; + }; +} diff --git a/containers/vaultwarden/default.nix b/containers/vaultwarden/default.nix new file mode 100644 index 0000000..ee5cc5e --- /dev/null +++ b/containers/vaultwarden/default.nix @@ -0,0 +1,34 @@ +{ ... }: +let + directories = [ + "/opt/vaultwarden" + ]; + domain = "crypt.tdback.net"; + port = "11001"; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.vaultwarden = { + image = "vaultwarden/server:latest"; + autoStart = true; + ports = [ + "${port}:80" + ]; + volumes = [ + "/opt/vaultwarden/data:/data" + ]; + environment = { + DOMAIN = domain; + WEBSOCKET_ENABLED = "true"; + SIGNUPS_ALLOWED = "false"; + SHOW_PASSWORD_HINT = "false"; + }; + }; + + services.caddy.virtualHosts."${domain}".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${port} { + header_up X-Real-IP {remote_host} + } + ''; +} diff --git a/containers/watchtower/default.nix b/containers/watchtower/default.nix new file mode 100644 index 0000000..bc819cd --- /dev/null +++ b/containers/watchtower/default.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + virtualisation.oci-containers.containers.watchtower = { + image = "containrrr/watchtower:latest"; + autoStart = true; + volumes = [ + "/var/run/podman/podman.sock:/var/run/docker.sock:ro" + "/etc/localtime:/etc/localtime:ro" + ]; + environment = { + WATCHTOWER_CLEANUP = "true"; + WATCHTOWER_SCHEDULE = "0 0 5 * * *"; + }; + }; +} diff --git a/dots/alacritty/default.nix b/dots/alacritty/default.nix new file mode 100644 index 0000000..f380201 --- /dev/null +++ b/dots/alacritty/default.nix @@ -0,0 +1,74 @@ +{ pkgs, ... }: +{ + programs.alacritty = { + enable = true; + package = pkgs.alacritty; + settings = { + env.TERM = "xterm-256color"; + mouse.hide_when_typing = true; + scrolling.history = 10000; + + window = { + decorations = "None"; + opacity = 1.0; + title = "Alacritty"; + padding = { + x = 5; + y = 0; + }; + }; + + cursor.style.blinking = "Never"; + + font = { + size = 13.0; + normal = { + family = "Iosevka Comfy Motion Fixed"; + style = "Regular"; + }; + italic = { + family = "Iosevka Comfy Motion Fixed"; + style = "Italic"; + }; + bold = { + family = "Iosevka Comfy Motion Fixed"; + style = "Bold"; + }; + bold_italic = { + family = "Iosevka Comfy Motion Fixed"; + style = "Bold Italic"; + }; + }; + + # Tomorrow Night Bright colorscheme. + colors = { + draw_bold_text_with_bright_colors = true; + + primary = { + background = "#000000"; + foreground = "#eaeaea"; + }; + normal = { + black = "#000000"; + red = "#d54e53"; + green = "#b9ca4a"; + yellow = "#e6c547"; + blue = "#7aa6da"; + magenta = "#c397d8"; + cyan = "#70c0ba"; + white = "#424242"; + }; + bright = { + black = "#666666"; + red = "#ff3334"; + green = "#9ec400"; + yellow = "#e7c547"; + blue = "#7aa6da"; + magenta = "#b77ee0"; + cyan = "#54ced6"; + white = "#2a2a2a"; + }; + }; + }; + }; +} diff --git a/dots/bspwm/default.nix b/dots/bspwm/default.nix new file mode 100644 index 0000000..28ac23e --- /dev/null +++ b/dots/bspwm/default.nix @@ -0,0 +1,42 @@ +{ pkgs, ... }: +{ + xsession.windowManager.bspwm = { + enable = true; + package = pkgs.bspwm; + + extraConfig = '' + ${pkgs.bspwm}/bin/bspc monitor -d 1 2 3 4 5 6 7 8 9 + ''; + + settings = { + window_gap = 8; + border_width = 1; + top_padding = 2; + bottom_padding = 2; + right_padding = 2; + left_padding = 2; + top_monocle_padding = 0; + bottom_monocle_padding = 0; + right_monocle_padding = 0; + left_monocle_padding = 0; + split_ratio = 0.5; + borderless_monocle = true; + gapless_monocle = true; + normal_border_color = "#3B4252"; + active_border_color = "#3B4252"; + focused_border_color = "#3B4252"; + presel_feedback_color = "#D8DEE9"; + }; + + rules = { + "Zathura".state = "tiled"; + }; + + startupPrograms = [ + "${pkgs.xorg.setxkbmap}/bin/setxkbmap -layout us" + "${pkgs.xorg.xsetroot}/bin/xsetroot -cursor_name left_ptr" + "${pkgs.xorg.xset}/bin/xset r rate 350 40" + "~/.fehbg" + ]; + }; +} diff --git a/dots/desktop/default.nix b/dots/desktop/default.nix new file mode 100644 index 0000000..9aa3f59 --- /dev/null +++ b/dots/desktop/default.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: +{ + qt = { + enable = true; + platformTheme.name = "gtk3"; + style = { + name = "adwaita-dark"; + package = pkgs.adwaita-qt; + }; + }; + + gtk = { + enable = true; + gtk3.extraConfig.gtk-application-prefer-dark-theme = 1; + gtk4.extraConfig.gtk-application-prefer-dark-theme = 1; + }; +} diff --git a/dots/dunst/default.nix b/dots/dunst/default.nix new file mode 100644 index 0000000..132e32b --- /dev/null +++ b/dots/dunst/default.nix @@ -0,0 +1,30 @@ +{ pkgs, ... }: +{ + services.dunst = { + enable = true; + package = pkgs.dunst; + + settings = { + global = { + width = 300; + height = 300; + offset = "30x50"; + origin = "top-right"; + frame_color = "#2c363c"; + font = "Iosevka Comfy Motion Fixed 12"; + }; + + urgency_normal = { + background = "#37474f"; + foreground = "eceff1"; + timeout = 5; + }; + }; + + iconTheme = { + name = "Papirus-Dark"; + package = pkgs.papirus-icon-theme; + size = "16x16"; + }; + }; +} diff --git a/dots/email/default.nix b/dots/email/default.nix new file mode 100644 index 0000000..9ff83c4 --- /dev/null +++ b/dots/email/default.nix @@ -0,0 +1,78 @@ +{ pkgs, ... }: +{ + accounts.email = { + maildirBasePath = "mail"; + + accounts.fastmail = { + primary = true; + address = "tyler@tdback.net"; + userName = "tyler@tdback.net"; + realName = "Tyler Dunneback"; + passwordCommand = "${pkgs.age}/bin/age -d -i ~/.ssh/email ~/vault/mail.age"; + + folders = { + inbox = "Inbox"; + drafts = "Drafts"; + sent = "Sent"; + trash = "Trash"; + }; + + imap = { + host = "imap.fastmail.com"; + port = 993; + tls = { + enable = true; + certificatesFile = "/etc/ssl/certs/ca-certificates.crt"; + }; + }; + + smtp = { + host = "smtp.fastmail.com"; + port = 465; + tls = { + enable = true; + useStartTls = false; + certificatesFile = "/etc/ssl/certs/ca-certificates.crt"; + }; + }; + + mbsync = { + enable = true; + create = "both"; + expunge = "none"; + subFolders = "Verbatim"; + patterns = [ "*" ]; + }; + + msmtp = { + enable = true; + extraConfig = { + logfile = "~/.cache/msmtp/msmtp.log"; + }; + }; + + neomutt = { + enable = true; + sendMailCommand = "msmtp"; + mailboxType = "maildir"; + extraMailboxes = [ + "Drafts" + "Sent" + "Trash" + "Archive" + ]; + }; + }; + }; + + programs = { + mbsync.enable = true; + msmtp.enable = true; + }; + + services.mbsync = { + enable = true; + package = pkgs.isync; + frequency = "*:0/5"; + }; +} diff --git a/dots/firefox/default.nix b/dots/firefox/default.nix new file mode 100644 index 0000000..c2ae82f --- /dev/null +++ b/dots/firefox/default.nix @@ -0,0 +1,123 @@ +{ config, pkgs, ... }: +let + lock-false = { + Value = false; + Status = "locked"; + }; + lock-true = { + Value = true; + Status = "locked"; + }; +in +{ + programs.firefox = { + enable = true; + package = pkgs.firefox; + + policies = { + # about:policies + DisableTelemetry = true; + DisableFirefoxStudies = true; + DisablePocket = true; + DisableFirefoxAccounts = true; + DisableAccounts = true; + DisplayBookmarksToolbar = "newtab"; + DisplayMenuBar = "default-off"; + SearchBar = "unified"; + OfferToSaveLogins = false; + EnableTrackingProtection = { + Value= true; + Locked = true; + Cryptomining = true; + Fingerprinting = true; + }; + + # about:config + Preferences = { + "browser.contentblocking.category" = { Value = "strict"; Status = "locked"; }; + "extensions.pocket.enabled" = lock-false; + "extensions.screenshots.disabled" = lock-true; + "browser.topsites.contile.enabled" = lock-false; + "browser.formfill.enable" = lock-false; + "browser.search.suggest.enabled" = lock-false; + "browser.search.suggest.enabled.private" = lock-false; + "browser.urlbar.suggest.searches" = lock-false; + "browser.urlbar.showSearchSuggestionsFirst" = lock-false; + "browser.newtabpage.activity-stream.feeds.section.topstories" = lock-false; + "browser.newtabpage.activity-stream.feeds.snippets" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includePocket" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includeDownloads" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includeVisited" = lock-false; + "browser.newtabpage.activity-stream.showSponsored" = lock-false; + "browser.newtabpage.activity-stream.system.showSponsored" = lock-false; + "browser.newtabpage.activity-stream.showSponsoredTopSites" = lock-false; + }; + + ExtensionSettings = { + # Block all extensions except those defined below. + "*".installation_mode = "blocked"; + + # uBlock Origin + "uBlock0@raymondhill.net" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + installation_mode = "force_installed"; + }; + + # Bitwarden + "{446900e4-71c2-419f-a6a7-df9c091e268b}" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi"; + installation_mode = "force_installed"; + }; + + # Dark Reader + "addon@darkreader.org" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/darkreader/latest.xpi"; + installation_mode = "force_installed"; + }; + }; + }; + + profiles = { + "${config.home.username}" = { + search = { + force = true; + default = "searx"; + order = [ "searx" ]; + engines = { + "Amazon.com".metaData.hidden = true; + "Bing".metaData.hidden = true; + "eBay".metaData.hidden = true; + "Google".metaData.hidden = true; + "Wikipedia (en)".metaData.alias = "@w"; + + "searx" = { + urls = [{ template = "http://10.0.0.203:8888/?q={searchTerms}"; }]; + updateInterval = 24 * 60 * 60 * 1000; # every day + definedAliases = [ "@sx" ]; + }; + + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { name = "type"; value = "packages"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }]; + iconUpdateURL = "https://wiki.nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; # every day + definedAliases = [ "@nw" ]; + }; + }; + }; + }; + }; + }; +} diff --git a/dots/irc/default.nix b/dots/irc/default.nix new file mode 100644 index 0000000..bc96909 --- /dev/null +++ b/dots/irc/default.nix @@ -0,0 +1,30 @@ +{ ... }: +let + user = "tdback"; +in +{ + programs.irssi = { + enable = true; + + extraConfig = '' + settings = { core = { real_name = "${user}"; }; }; + ''; + + networks = { + liberachat = { + nick = "${user}"; + saslExternal = true; + server = { + address = "irc.libera.chat"; + port = 6697; + autoConnect = true; + ssl = { + enable = true; + verify = true; + certificateFile = "/home/${user}/.irssi/certs/libera.pem"; + }; + }; + }; + }; + }; +} diff --git a/dots/mpd/default.nix b/dots/mpd/default.nix new file mode 100644 index 0000000..d7338cb --- /dev/null +++ b/dots/mpd/default.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: +{ + services.mpd = { + enable = true; + package = pkgs.mpd; + + network = { + listenAddress = "127.0.0.1"; + port = 6600; + }; + + musicDirectory = "~/media/music"; + + extraConfig = '' + log_file "syslog" + max_output_buffer_size "16384" + + restore_paused "yes" + auto_update "yes" + + audio_output { + type "pulse" + name "pulseaudio" + } + + audio_output { + type "fifo" + name "Visualizer feed" + path "/tmp/mpd.fifo" + format "44100:16:2" + } + ''; + }; +} diff --git a/dots/ncmpcpp/default.nix b/dots/ncmpcpp/default.nix new file mode 100644 index 0000000..a201e88 --- /dev/null +++ b/dots/ncmpcpp/default.nix @@ -0,0 +1,65 @@ +{ pkgs, ... }: +{ + programs.ncmpcpp = { + enable = true; + package = pkgs.ncmpcpp.override { visualizerSupport = true; }; + mpdMusicDir = "~/Media/Music"; + settings = { + ncmpcpp_directory = "~/.config/ncmpcpp"; + lyrics_directory = "~/.local/share/lyrics"; + song_list_format = "{%a - }{%t}|{$8%f$9}$R{$3%l$9}"; + song_status_format = "{{%a{ \"%b\"{ (%y)}} - }{%t}}|{%f}"; + song_library_format = "{%n - }{%t}|{%f}"; + alternative_header_first_line_format = "$b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b"; + alternative_header_second_line_format = "{{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D}"; + current_item_prefix = "$(yellow)$r"; + current_item_suffix = "$/r$(end)"; + current_item_inactive_column_prefix = "$(white)$r"; + current_item_inactive_column_suffix = "$/r$(end)"; + now_playing_prefix = "$b"; + now_playing_suffix = "$/b"; + browser_playlist_prefix = "$2playlist$9 "; + selected_item_prefix = "$6"; + selected_item_suffix = "$9"; + modified_item_prefix = "$3> $9"; + song_window_title_format = "{%a - }{%t}|{%f}"; + browser_sort_mode = "type"; + browser_sort_format = "{%a - }{%t}|{%f} {%l}"; + visualizer_data_source = "/tmp/mpd.fifo"; + visualizer_output_name = "Visualizer feed"; + visualizer_in_stereo = true; + visualizer_type = "spectrum"; + visualizer_look = "●▮"; + visualizer_color = "blue, cyan, green, yellow, magenta, red"; + visualizer_spectrum_smooth_look = true; + }; + + bindings = [ + { key = "j"; command = "scroll_down"; } + { key = "k"; command = "scroll_up"; } + { key = "h"; command = [ "previous_column" "jump_to_parent_directory" ]; } + { key = "l"; command = [ "next_column" "enter_directory" "run_action" "play_item" ]; } + { key = "u"; command = "page_up"; } + { key = "d"; command = "page_down"; } + { key = "ctrl-u"; command = "page_up"; } + { key = "ctrl-d"; command = "page_down"; } + { key = "g"; command = "move_home"; } + { key = "G"; command = "move_end"; } + { key = "n"; command = "next_found_item"; } + { key = "N"; command = "previous_found_item"; } + { key = "J"; command = "move_sort_order_down"; } + { key = "K"; command = "move_sort_order_up"; } + { key = "f"; command = [ "show_browser" "change_browse_mode" ]; } + { key = "s"; command = [ "reset_search_engine" "show_search_engine" ]; } + { key = "m"; command = "toggle_media_library_columns_mode"; } + { key = "x"; command = "delete_playlist_items"; } + { key = "U"; command = "update_database"; } + { key = "P"; command = "show_playlist"; } + { key = "t"; command = "show_tag_editor"; } + { key = "v"; command = "show_visualizer"; } + { key = "."; command = "show_lyrics"; } + { key = "+"; command = "show_clock"; } + { key = "="; command = "volume_up"; } + ]; + }; +} diff --git a/dots/neomutt/default.nix b/dots/neomutt/default.nix new file mode 100644 index 0000000..243aa6b --- /dev/null +++ b/dots/neomutt/default.nix @@ -0,0 +1,69 @@ +{ pkgs, ... }: +{ + programs.neomutt = { + enable = true; + package = pkgs.neomutt; + + vimKeys = true; + sort = "reverse-date"; + + checkStatsInterval = 60; + + sidebar = { + enable = true; + shortPath = true; + width = 20; + }; + + binds = [ + { + map = [ "index" "pager" ]; + key = "\\Cp"; + action = "sidebar-prev"; + } + { + map = [ "index" "pager" ]; + key = "\\Cn"; + action = "sidebar-next"; + } + { + map = [ "index" "pager" ]; + key = "\\Cy"; + action = "sidebar-open"; + } + ]; + + macros = [ + { + map = [ "index" "pager" ]; + key = "gi"; + action = "=Inbox"; + } + { + map = [ "index" "pager" ]; + key = "gs"; + action = "=Sent"; + } + { + map = [ "index" "pager" ]; + key = "gd"; + action = "=Drafts"; + } + { + map = [ "index" "pager" ]; + key = "gt"; + action = "=Trash"; + } + { + map = [ "index" "pager" ]; + key = "ga"; + action = "=Archive"; + } + { + map = [ "index" ]; + key = "S"; + action = "${pkgs.isync}/bin/mbsync -a"; + } + ]; + }; +} diff --git a/dots/polybar/default.nix b/dots/polybar/default.nix new file mode 100644 index 0000000..2de63a7 --- /dev/null +++ b/dots/polybar/default.nix @@ -0,0 +1,163 @@ +{ pkgs, ... }: +{ + services.polybar = { + enable = true; + package = pkgs.polybar.override { + pulseSupport = true; + }; + + script = "polybar main &"; + + settings = + let + colors = { + background = "#050505"; + background-alt = "#373B41"; + foreground = "#F1F1F1"; + focused = "#4D406B"; + primary = "#E04845"; + occupied = "#505050"; + secondary = "#8ABEB7"; + alert = "#A54242"; + disabled = "#707880"; + }; + in + { + "bar/main" = { + width = "100%"; + height = "18pt"; + radius = 0; + + background = "${colors.background}"; + foreground = "${colors.foreground}"; + + line.size = "3pt"; + + border = { + size = "0pt"; + color = "#00000000"; + }; + + padding = { + left = 1; + right = 1; + }; + + module.margin = 1; + + separator.foreground = "${colors.disabled}"; + + font = [ "JetBrainsMonoNerdFont:size=9" ]; + + modules = { + left = "bspwm"; + right = "volume cpu date"; + }; + + cursor.click = "pointer"; + + wm.restack = "bspwm"; + }; + + "module/bspwm" = { + type = "internal/bspwm"; + pin.workspaces = true; + + label = { + focused = { + text = "%index%"; + foreground = "${colors.foreground}"; + padding = 1; + }; + + occupied = { + text = "%index%"; + foreground = "${colors.occupied}"; + padding = 1; + }; + + urgent = { + text = "%index%"; + foreground = "${colors.foreground}"; + background = "${colors.background-alt}"; + padding = 1; + }; + + empty = { + text = ""; + padding = 1; + }; + }; + }; + + "module/cpu" = { + type = "internal/cpu"; + interval = 2; + format = ""; + ramp.coreload = { + text = [ "▁" "▂" "▃" "▄" "▅" "▆" "▇" ]; + spacing = 0; + }; + }; + + "module/volume" = { + type = "internal/pulseaudio"; + format = { + volume = { + text = ""; + background = "${colors.foreground}"; + }; + }; + + label = { + volume = { + text = "%percentage%%"; + foreground = "${colors.foreground}"; + background = "${colors.background}"; + padding.left = 2; + }; + + muted = { + text = " 0%"; + foreground = "${colors.foreground}"; + background = "${colors.background}"; + padding = 0; + }; + }; + + ramp.volume = { + text = [ "" "" "" ]; + foreground = "${colors.foreground}"; + background = "${colors.background}"; + padding.right = 0; + }; + + click.right = "${pkgs.pavucontrol}/bin/pavucontrol"; + }; + + "module/date" = { + type = "internal/date"; + interval = 1; + + date = { + text = "%a, %b %d"; + alt = "%a, %b %d"; + }; + time = { + text = "%H:%M %p"; + alt = "%H:%M:%S"; + }; + + label = "%date% %time%"; + }; + + "settings" = { + screenchange.reload = true; + pseudo.transparency = true; + }; + }; + }; + + # Make sure polybar starts only during graphical sessions. + systemd.user.services.polybar.Install.WantedBy = [ "graphical-session.target" ]; +} diff --git a/dots/rofi/default.nix b/dots/rofi/default.nix new file mode 100644 index 0000000..b6c15d7 --- /dev/null +++ b/dots/rofi/default.nix @@ -0,0 +1,81 @@ +{ pkgs, config, ... }: +{ + programs.rofi = { + enable = true; + package = pkgs.rofi; + font = "Iosevka Comfy Motion Fixed 12"; + location = "center"; + extraConfig = { + modi = "window,run,drun"; + icon-theme = "Papirus"; + show-icons = true; + display-drun = ""; + display-window = ""; + drun-display-format = "{icon} {name}"; + }; + theme = + let + inherit (config.lib.formats.rasi) mkLiteral; + in + { + "*" = { + bg = mkLiteral "#050505"; + bg-alt = mkLiteral "#191919"; + fg = mkLiteral "#FFFFFF"; + fg-alt = mkLiteral"#787c99"; + background-color = mkLiteral "@bg"; + border = 0; + margin = 0; + padding = 0; + spacing = 0; + }; + + "window" = { + width = mkLiteral "40%"; + }; + + "element" = { + padding = 12; + text-color = mkLiteral "@fg-alt"; + }; + + "element selected" = { + text-color = mkLiteral "@fg"; + }; + + "element-text" = { + background-color = mkLiteral "inherit"; + text-color = mkLiteral "inherit"; + vertical-align = mkLiteral "0.5"; + }; + + "element-icon" = { + size = 38; + }; + + "entry" = { + background-color = mkLiteral "@bg-alt"; + text-color = mkLiteral "@fg"; + padding = 14; + placeholder = "Search..."; + }; + + "inputbar" = { + children = map mkLiteral [ "prompt" "entry" ]; + }; + + "listview" = { + columns = 2; + lines = 6; + background-color = mkLiteral "@bg"; + }; + + "prompt" = { + enabled = true; + background-color = mkLiteral "@bg-alt"; + text-color = mkLiteral "@fg"; + padding = mkLiteral "14 10 0 14"; + }; + }; + }; +} diff --git a/dots/sxhkd/default.nix b/dots/sxhkd/default.nix new file mode 100644 index 0000000..f472f1d --- /dev/null +++ b/dots/sxhkd/default.nix @@ -0,0 +1,42 @@ +{ pkgs, ... }: +{ + services.sxhkd = { + enable = true; + package = pkgs.sxhkd; + keybindings = { + # Program hotkeys. + "alt + Tab" = "rofi -show window"; + "super + r" = "rofi -show drun"; + "super + x" = "alacritty"; + "super + b" = "firefox"; + "super + p" = "flameshot full -p $HOME/.local/screenshots"; + "super + shift + p" = "flameshot gui -p $HOME/.local/screenshots"; + "super + Escape" = "systemctl --user restart polybar"; + "super + alt + {q,r}" = "bspc {quit,wm -r}"; + + # Function hotkeys. + "XF86AudioPrev" = "mpc prev"; + "XF86AudioNext" = "mpc next"; + "XF86AudioPlay" = "mpc toggle"; + "XF86AudioLowerVolume" = "pamixer -d 5"; + "XF86AudioRaiseVolume" = "pamixer -i 5"; + "XF86AudioMute" = "pamixer -t"; + + # Manipulate window manager. + "super + q" = "bspc node -{c,k}"; + "super + f" = "bspc node focused.tiled -t fullscreen"; + "super + t" = "bspc node focused.fullscreen -t tiled"; + "super + shift + f" = "bspc node focused.tiled -t floating"; + "super + shift + t" = "bspc node focused.floating -t tiled"; + "super + {_,shift + }{h,j,k,l}" = "bspc node -{f,s} {west,south,north,east}"; + "super + {_,shift}c" = "bspc node -f {next,prev}.local.!hidden.window"; + "super + bracket{left,right}" = "bspc desktop -f {prev,next}.local"; + "super + {grave,Tab}" = "bspc {node,desktop} -f last"; + "super + {o,i}" = "bspc wm -h off; bspc node {older,newer} -f; bspc wm -h on"; + "super + {_,shift + }{1-9,0}" = "bspc {desktop -f, node -d} '^{1-9,10}'"; + "super + alt + {h,j,k,l}" = "bspc node -z {left -20 0, bottom 0 20, top 0 -20, right 20 0}"; + "super + alt + shift {h,j,k,l}" = "bspc node -z {right -20 0, top 0 20, bottom 0 -20, left 20 0}"; + "super + {Left,Down,Up,Right}" = "bspc node -v {-20 0,0 20,0 -20,20 0}"; + }; + }; +} diff --git a/dots/tmux/default.nix b/dots/tmux/default.nix new file mode 100644 index 0000000..b7a381c --- /dev/null +++ b/dots/tmux/default.nix @@ -0,0 +1,61 @@ +{ pkgs, ... }: +{ + programs.tmux = { + enable = true; + package = pkgs.tmux; + + terminal = "tmux-256color"; + mouse = true; + escapeTime = 0; + + clock24 = true; + baseIndex= 0; + + secureSocket = true; + aggressiveResize = true; + + historyLimit = 10000; + + prefix = "C-t"; + extraConfig = '' + # Prevent detaching from tmux when closing a session. + set -g detach-on-destroy off + + # Kill the current session. + bind X kill-session + + # Splitting panes. + unbind v + unbind h + unbind % + unbind '"' + bind v split-window -h -c "#{pane_current_path}" # split vertically + bind V split-window -f -h -l 72 -c "#{pane_current_path}" # split vertically, but a smaller pane + bind h split-window -v -c "#{pane_current_path}" # split horizontally + bind H split-window -f -v -l 12 -c "#{pane_current_path}" # split horizontally, but a smaller pane + + # Navigating panes. + bind ^ last-window + bind C-h select-pane -L + bind C-j select-pane -D + bind C-k select-pane -U + bind C-l select-pane -R + + # Copy mode movements. + set-window-option -g mode-keys vi + unbind -T copy-mode-vi Space; # Default for begin-selection + unbind -T copy-mode-vi Enter; # Default for copy-selection + bind -T copy-mode-vi v send-keys -X begin-selection + bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -in -selection clipboard" + + # Customizing status bar. + set -g status-position bottom + set -g status-style 'bg=#050505 fg=#C5C8C6' + set -g status-right '#[fg=colour233,bg=colour241,bold] %m/%d #[fg=colour233,bg=colour245,bold] %H:%M ' + set -g status-right-length 50 + + setw -g window-status-current-format ' #I#[fg=colour250]:#[fg=colour255]#W#[fg=colour50]#F' + setw -g window-status-format ' #I#[fg=colour237]:#[fg=colour250]#W#[fg=colour244]#F' + ''; + }; +} diff --git a/dots/zsh/default.nix b/dots/zsh/default.nix new file mode 100644 index 0000000..f637079 --- /dev/null +++ b/dots/zsh/default.nix @@ -0,0 +1,94 @@ +{ pkgs, ... }: +{ + programs = { + zoxide = { + enable = true; + enableZshIntegration = true; + options = [ + "--cmd cd" + ]; + }; + + zsh = { + enable = true; + package = pkgs.zsh; + dotDir = ".config/zsh"; + + defaultKeymap = "viins"; + enableCompletion = true; + autosuggestion.enable = false; + + syntaxHighlighting = { + enable = true; + package = pkgs.zsh-syntax-highlighting; + }; + + history = { + save = 10000; + size = 10000; + ignoreDups = true; + }; + + historySubstringSearch = { + enable = true; + searchUpKey = "^P"; + searchDownKey = "^N"; + }; + + envExtra = '' + export EDITOR=nvim || export EDITOR=vim + export BROWSER=firefox + + # Clean up the home folder. + export GCC_COLORS="error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01" + export GNUPGHOME="$XDG_DATA_HOME/gnupg" + export _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME/java" + export LC_ALL=en_US.UTF-8 + export LESSHISTFILE="-" + export MANPAGER="nvim +Man!" + export PARALLEL_HOME="$XDG_CONFIG_HOME/parallel" + export SQLITE_HISTORY="$XDG_DATA_HOME/sqlite_history" + + # Add these directories to PATH on shell startup. + PATH=$PATH:$HOME/scripts + PATH=$PATH:$HOME/.local/bin + ''; + + initExtra = '' + autoload -U colors && colors + # Manually set the prompt. + PS1=" + %{$fg[blue]%}%n %{$fg[yellow]%}at %{$fg[blue]%}%m %{$fg[yellow]%}in %{$fg[blue]%}%~ + %{$fg[yellow]%}λ%{$reset_color%} " + + set -o noclobber + setopt interactive_comments + + export KEYTIMEOUT=1 + + # Use 'k' and 'j' for substring searching when in cmd mode. + bindkey -M vicmd 'k' history-substring-search-up + bindkey -M vicmd 'j' history-substring-search-down + + # Use for autosuggestions, similar to nvim. + bindkey '^Y' autosuggest-accept + + # Cycle back through previous suggestions with . + bindkey '^[[Z' reverse-menu-complete + ''; + + shellAliases = { + cp = "cp -i"; + mv = "mv -i"; + rm = "rm -I"; + ls = "ls --color=auto"; + cat = "bat -pp"; + grep = "grep --color=auto"; + diff = "diff --color=auto"; + mutt = "neomutt"; + song = "yt-dlp --continue --no-check-certificate --format=bestaudio -x --add-metadata --audio-format=flac"; + mkdir = "mkdir -p"; + }; + }; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d62822c --- /dev/null +++ b/flake.lock @@ -0,0 +1,148 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1726989464, + "narHash": "sha256-Vl+WVTJwutXkimwGprnEtXc/s/s8sMuXzqXaspIGlwM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "2f23fa308a7c067e52dfcc30a0758f47043ec176", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-24.05", + "repo": "home-manager", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1729691686, + "narHash": "sha256-BAuPWW+9fa1moZTU+jFh+1cUtmsuF8asgzFwejM4wac=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "32e940c7c420600ef0d1ef396dc63b04ee9cad37", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1729665710, + "narHash": "sha256-AlcmCXJZPIlO5dmFzV3V2XF6x/OpNWUV8Y/FMPGd8Z4=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "2768c7d042a37de65bb1b5b3268fc987e534c49d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "home-manager": "home-manager_2", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f81bf29 --- /dev/null +++ b/flake.nix @@ -0,0 +1,184 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager/release-24.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { self + , nixpkgs + , nixpkgs-unstable + , home-manager + , agenix + , ... + } @ inputs: + let + inherit (self) outputs; + in + { + overlays = import ./overlays { inherit inputs; }; + + nixosConfigurations = { + woodpecker = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Base configuration and modules. + ./modules/bspwm + ./modules/fstrim + ./modules/libvirtd + ./modules/nvidia + ./modules/pipewire + ./modules/steam + ./modules/wireshark + + # System configuration. + ./hosts/workstations + ./hosts/workstations/woodpecker + + # User configuration. + ./users/tdback + home-manager.nixosModules.home-manager { + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users.tdback = import ./users/tdback/dots.nix; + extraSpecialArgs = { inherit inputs; }; + }; + } + ]; + specialArgs = { inherit inputs outputs; }; + }; + + sparrow = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Base configuration and modules. + ./modules/bspwm + ./modules/pipewire + ./modules/vpn + + # System configuration. + ./hosts/workstations + ./hosts/workstations/sparrow + + # User configuration. + ./users/tdback + home-manager.nixosModules.home-manager { + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users.tdback = import ./users/tdback/dots.nix; + extraSpecialArgs = { inherit inputs; }; + }; + } + ]; + specialArgs = { inherit inputs outputs; }; + }; + + raindog = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Base configuration and modules. + ./containers/pihole + ./modules/motd + ./modules/podman + ./modules/searx + ./modules/ssh + + # System configuration. + ./hosts/servers + ./hosts/servers/raindog + + # User configuration. + ./users/tdback + ]; + specialArgs = { inherit inputs outputs; }; + }; + + oasis = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Base configuration and modules. + ./modules/forgejo + ./modules/motd + ./modules/podman + ./modules/proxy + ./modules/pushover + ./modules/sftpgo + ./modules/ssh + ./modules/wireguard + ./modules/zfs + + # System configuration and secrets. + ./hosts/servers + ./hosts/servers/oasis + agenix.nixosModules.default + + # User configuration. + ./users/tdback + ]; + specialArgs = { inherit inputs outputs; }; + }; + + hive = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Base configuration and modules. + ./modules/fediverse + ./modules/mealie + ./modules/motd + ./modules/proxy + ./modules/ssh + ./modules/wireguard + + # System configuration. + ./hosts/servers + ./hosts/servers/hive + + # User configuration. + ./users/tdback + ]; + specialArgs = { inherit inputs outputs; }; + }; + + eden = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Base configuration and modules. + ./containers/freshrss + ./containers/jellyfin + ./containers/navidrome + ./containers/pinchflat + ./containers/stirling-pdf + ./containers/vaultwarden + ./containers/watchtower + ./modules/immich + ./modules/motd + ./modules/podman + ./modules/proxy + ./modules/pushover + ./modules/ssh + ./modules/wireguard + ./modules/zfs + + # System configuration and secrets. + ./hosts/servers + ./hosts/servers/eden + agenix.nixosModules.default + + # User configuration. + ./users/tdback + ]; + specialArgs = { inherit inputs outputs; }; + }; + }; + }; +} diff --git a/hosts/servers/default.nix b/hosts/servers/default.nix new file mode 100644 index 0000000..24d66ac --- /dev/null +++ b/hosts/servers/default.nix @@ -0,0 +1,93 @@ +{ inputs, outputs, lib, pkgs, ... }: +{ + system.stateVersion = "24.05"; + + nix = { + settings = { + trusted-users = [ "@wheel" "root" ]; + experimental-features = lib.mkDefault [ "nix-command" "flakes" ]; + auto-optimise-store = true; + }; + + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 14d"; + }; + }; + + nixpkgs = { + overlays = [ outputs.overlays.unstable-packages ]; + config = { + allowUnfree = true; + allowUnfreePredicate = (_: true); + }; + }; + + system.autoUpgrade = { + enable = true; + flake = inputs.self.outPath; + flags = [ + "--update-input" + "nixpkgs" + "-L" + ]; + dates = "Sat *-*-* 06:00:00"; + randomizedDelaySec = "45min"; + allowReboot = true; + }; + + security = { + sudo.enable = lib.mkDefault false; + doas = { + enable = lib.mkDefault true; + extraRules = [{ + groups = [ "wheel" ]; + keepEnv = true; + persist = true; + }]; + }; + + polkit.enable = true; + }; + + networking.firewall.enable = true; + + time.timeZone = "America/Detroit"; + + i18n.defaultLocale = "en_US.UTF-8"; + + programs = { + git.enable = true; + htop.enable = true; + + neovim = { + enable = true; + package = pkgs.unstable.neovim-unwrapped; + viAlias = true; + vimAlias = true; + defaultEditor = true; + }; + + zsh = { + enable = true; + enableCompletion = true; + syntaxHighlighting.enable = true; + promptInit = '' + PS1="%m%% " + ''; + loginShellInit = '' + if command -v motd &> /dev/null; then + motd + fi + ''; + }; + }; + + environment.systemPackages = with pkgs; [ + curl + fd + ripgrep + rsync + ]; +} diff --git a/hosts/servers/eden/default.nix b/hosts/servers/eden/default.nix new file mode 100644 index 0000000..7d3d138 --- /dev/null +++ b/hosts/servers/eden/default.nix @@ -0,0 +1,43 @@ +{ lib, ... }: +{ + imports = [ + ./hardware.nix + ]; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + zfs.extraPools = [ "lagoon" ]; + }; + + networking = { + hostId = "bd03847d"; # Required for ZFS support. + hostName = "eden"; + networkmanager.enable = true; + }; + + motd = { + networkInterfaces = lib.lists.singleton "eno1"; + servicesToCheck = [ + "caddy" + "immich-machine-learning" + "immich-server" + "postgresql" + "redis-immich" + "zfs-zed" + ]; + }; + + users = { + users.share = { + uid = 994; + isSystemUser = true; + group = "share"; + }; + groups.share = { + gid = 994; + }; + }; +} diff --git a/hosts/servers/eden/hardware.nix b/hosts/servers/eden/hardware.nix new file mode 100644 index 0000000..00210c4 --- /dev/null +++ b/hosts/servers/eden/hardware.nix @@ -0,0 +1,38 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/f3bedccb-3f2b-49ae-9be4-5ec9fe683027"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/78C3-E7F8"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/servers/hive/default.nix b/hosts/servers/hive/default.nix new file mode 100644 index 0000000..9170487 --- /dev/null +++ b/hosts/servers/hive/default.nix @@ -0,0 +1,26 @@ +{ lib, ... }: +{ + imports = [ + ./hardware.nix + ]; + + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + networking = { + hostName = "hive"; + networkmanager.enable = true; + }; + + motd = { + networkInterfaces = lib.lists.singleton "eno1"; + servicesToCheck = [ + "caddy" + "gotosocial" + "mealie" + "murmur" + ]; + }; +} diff --git a/hosts/servers/hive/hardware.nix b/hosts/servers/hive/hardware.nix new file mode 100644 index 0000000..9e7a2f0 --- /dev/null +++ b/hosts/servers/hive/hardware.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/e336b96d-b3b4-4098-a0ca-9001fd381f88"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/F804-40A9"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp6s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/servers/oasis/default.nix b/hosts/servers/oasis/default.nix new file mode 100644 index 0000000..234103f --- /dev/null +++ b/hosts/servers/oasis/default.nix @@ -0,0 +1,31 @@ +{ lib, ... }: +{ + imports = [ + ./hardware.nix + ]; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + zfs.extraPools = [ "tank" ]; + }; + + networking = { + hostId = "7a7d723a"; # Required for ZFS support. + hostName = "oasis"; + networkmanager.enable = true; + }; + + motd = { + networkInterfaces = lib.lists.singleton "enp59s0"; + servicesToCheck = [ + "caddy" + "forgejo" + "runner" + "sftpgo" + "zfs-zed" + ]; + }; +} diff --git a/hosts/servers/oasis/hardware.nix b/hosts/servers/oasis/hardware.nix new file mode 100644 index 0000000..3870379 --- /dev/null +++ b/hosts/servers/oasis/hardware.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/3e333010-7dae-47cf-9288-85d58ddda699"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/8430-1FF8"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp59s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlo1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/servers/raindog/default.nix b/hosts/servers/raindog/default.nix new file mode 100644 index 0000000..84a194f --- /dev/null +++ b/hosts/servers/raindog/default.nix @@ -0,0 +1,34 @@ +{ lib, ... }: +{ + imports = [ + ./hardware.nix + ]; + + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + networking = { + hostName = "raindog"; + networkmanager.enable = true; + }; + + motd = { + networkInterfaces = lib.lists.singleton "eno1"; + servicesToCheck = [ + "searx" + ]; + }; + + users = { + users.share = { + uid = 994; + isSystemUser = true; + group = "share"; + }; + groups.share = { + gid = 994; + }; + }; +} diff --git a/hosts/servers/raindog/hardware.nix b/hosts/servers/raindog/hardware.nix new file mode 100644 index 0000000..b2a5571 --- /dev/null +++ b/hosts/servers/raindog/hardware.nix @@ -0,0 +1,38 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/d62103eb-e154-4b71-b813-54ca76815a80"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/5972-1878"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/workstations/default.nix b/hosts/workstations/default.nix new file mode 100644 index 0000000..0890962 --- /dev/null +++ b/hosts/workstations/default.nix @@ -0,0 +1,80 @@ +{ outputs, lib, pkgs, ... }: +{ + system.stateVersion = "24.05"; + + nix = { + settings = { + trusted-users = [ "@wheel" "root" ]; + experimental-features = lib.mkDefault [ "nix-command" "flakes" ]; + auto-optimise-store = true; + }; + + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 14d"; + }; + }; + + nixpkgs = { + overlays = [ outputs.overlays.unstable-packages ]; + config = { + allowUnfree = true; + allowUnfreePredicate = (_: true); + }; + }; + + security = { + sudo.enable = lib.mkDefault false; + doas = { + enable = lib.mkDefault true; + extraRules = [{ + groups = [ "wheel" ]; + keepEnv = true; + persist = true; + }]; + }; + + polkit.enable = true; + }; + + hardware.opengl = { + driSupport = true; + driSupport32Bit = true; + }; + + networking.firewall.enable = true; + + time.timeZone = "America/Detroit"; + + i18n.defaultLocale = "en_US.UTF-8"; + + programs = { + git.enable = true; + htop.enable = true; + neovim = { + enable = true; + package = pkgs.unstable.neovim-unwrapped; + viAlias = true; + vimAlias = true; + defaultEditor = true; + }; + }; + + environment.systemPackages = with pkgs; [ + rsync + xorg.libX11 + xorg.xset + ]; + + fonts.packages = with pkgs; [ + dejavu_fonts + dina-font + iosevka-comfy.comfy-motion-fixed + liberation_ttf + noto-fonts + noto-fonts-emoji + ubuntu_font_family + (nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) + ]; +} diff --git a/hosts/workstations/sparrow/default.nix b/hosts/workstations/sparrow/default.nix new file mode 100644 index 0000000..bab754c --- /dev/null +++ b/hosts/workstations/sparrow/default.nix @@ -0,0 +1,28 @@ +{ pkgs, ... }: +{ + imports = [ + ./hardware.nix + ]; + + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + networking = { + hostName = "sparrow"; + networkmanager.enable = true; + }; + + services = { + xserver.xkb.options = "ctrl:swapcaps"; + libinput.enable = true; + }; + + console.useXkbConfig = true; + + environment.systemPackages = with pkgs; [ + acpi + qbittorrent + ]; +} diff --git a/hosts/workstations/sparrow/hardware.nix b/hosts/workstations/sparrow/hardware.nix new file mode 100644 index 0000000..d40b232 --- /dev/null +++ b/hosts/workstations/sparrow/hardware.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/d296f7a3-68d2-406f-963d-8ec39ab0ea64"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/B159-723B"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [{ + device = "/.swapfile"; + }]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp59s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/workstations/woodpecker/default.nix b/hosts/workstations/woodpecker/default.nix new file mode 100644 index 0000000..1c4a52a --- /dev/null +++ b/hosts/workstations/woodpecker/default.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: +{ + imports = [ + ./hardware.nix + ]; + + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + networking = { + hostName = "woodpecker"; + networkmanager.enable = true; + }; + + environment.systemPackages = with pkgs; [ + mesa + ]; +} diff --git a/hosts/workstations/woodpecker/hardware.nix b/hosts/workstations/woodpecker/hardware.nix new file mode 100644 index 0000000..3fc71e9 --- /dev/null +++ b/hosts/workstations/woodpecker/hardware.nix @@ -0,0 +1,44 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/90ec7fc1-192e-4bb5-9bb5-5e2776435f8d"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/3A26-C3FB"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + fileSystems."/home" = + { device = "/dev/disk/by-uuid/cd7e081e-cd0b-4dc5-b41c-8dda26437a78"; + fsType = "ext4"; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp42s0.useDHCP = lib.mkDefault true; + # networking.interfaces.enp5s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/modules/bspwm/default.nix b/modules/bspwm/default.nix new file mode 100644 index 0000000..0aacc9d --- /dev/null +++ b/modules/bspwm/default.nix @@ -0,0 +1,16 @@ +{ ... }: +{ + services = { + xserver = { + enable = true; + xkb.layout = "us"; + displayManager.lightdm.enable = true; + windowManager.bspwm.enable = true; + }; + + displayManager.autoLogin = { + enable = true; + user = "tdback"; + }; + }; +} diff --git a/modules/fediverse/default.nix b/modules/fediverse/default.nix new file mode 100644 index 0000000..8235ead --- /dev/null +++ b/modules/fediverse/default.nix @@ -0,0 +1,27 @@ +{ pkgs, ... }: +let + domain = "social.tdback.net"; + port = 8080; +in +{ + services.gotosocial = { + enable = true; + package = pkgs.unstable.gotosocial; + + settings = { + application-name = "gotosocial"; + host = "${domain}"; + protocol = "https"; + bind-address = "localhost"; + port = port; + db-type = "sqlite"; + db-address = "/var/lib/gotosocial/database.sqlite"; + storage-local-base-path = "/var/lib/gotosocial/storage"; + }; + }; + + services.caddy.virtualHosts."${domain}".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${builtins.toString port} + ''; +} diff --git a/modules/forgejo/default.nix b/modules/forgejo/default.nix new file mode 100644 index 0000000..d0cf0cf --- /dev/null +++ b/modules/forgejo/default.nix @@ -0,0 +1,65 @@ +{ lib, config, pkgs, ... }: +let + domain = "git.tdback.net"; + port = 3000; +in +{ + services.forgejo = { + enable = true; + package = pkgs.unstable.forgejo; + stateDir = "/tank/forgejo"; + database.type = "postgres"; + lfs.enable = true; + settings = { + server = { + DOMAIN = domain; + ROOT_URL = "https://${domain}/"; + HTTP_PORT = port; + }; + service.DISABLE_REGISTRATION = true; + actions = { + ENABLED = true; + DEFAULT_ACTIONS_URL = "https://${domain}"; + }; + }; + }; + + age.secrets.forgejoAdminPass = { + file = ../../secrets/forgejoAdminPass.age; + mode = "770"; + owner = "forgejo"; + group = "forgejo"; + }; + + systemd.services.forgejo.preStart = + let + adminCmd = "${lib.getExe config.services.forgejo.package} admin user"; + pwd = config.age.secrets.forgejoAdminPass.path; + user = "tdback"; + email = "tyler@tdback.net"; + in '' + ${adminCmd} create --admin --email ${email} --username ${user} --password "$(tr -d '\n' < ${pwd})" || true + ''; + + age.secrets.forgejoRunnerToken.file = ../../secrets/forgejoRunnerToken.age; + services.gitea-actions-runner = { + package = pkgs.unstable.forgejo-runner; + instances.default = { + enable = true; + name = "monolith"; + url = "https://${domain}"; + tokenFile = config.age.secrets.forgejoRunnerToken.path; + labels = [ + "ubuntu-latest:docker://node:20-bookworm" + "ubuntu-22.04:docker://node:20-bookworm" + ]; + }; + }; + + services.openssh.settings.AllowUsers = [ "forgejo" ]; + + services.caddy.virtualHosts."${domain}".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${builtins.toString port} + ''; +} diff --git a/modules/fstrim/default.nix b/modules/fstrim/default.nix new file mode 100644 index 0000000..03da691 --- /dev/null +++ b/modules/fstrim/default.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + services.fstrim = { + enable = true; + interval = "weekly"; + }; +} diff --git a/modules/immich/default.nix b/modules/immich/default.nix new file mode 100644 index 0000000..29d0019 --- /dev/null +++ b/modules/immich/default.nix @@ -0,0 +1,27 @@ +{ inputs, pkgs, ... }: +{ + disabledModules = [ "services/databases/redis.nix" ]; + imports = [ + "${inputs.nixpkgs-unstable}/nixos/modules/services/web-apps/immich.nix" + "${inputs.nixpkgs-unstable}/nixos/modules/services/databases/redis.nix" + ]; + + services = { + immich = { + enable = true; + package = pkgs.unstable.immich; + host = "localhost"; + port = 2283; + mediaLocation = "/lagoon/media/immich"; + environment = { + IMMICH_LOG_LEVEL = "log"; + }; + }; + postgresql.package = pkgs.unstable.postgresql; + }; + + services.caddy.virtualHosts."photographs.tdback.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:2283 + ''; +} diff --git a/modules/libvirtd/default.nix b/modules/libvirtd/default.nix new file mode 100644 index 0000000..a09c876 --- /dev/null +++ b/modules/libvirtd/default.nix @@ -0,0 +1,17 @@ +{ config, ... }: +{ + virtualisation.libvirtd = { + enable = true; + qemu = { + ovmf.enable = true; + runAsRoot = false; + }; + onBoot = "ignore"; + onShutdown = "shutdown"; + }; + + programs.virt-manager.enable = true; + + # Add any users in the 'wheel' group to the 'libvirtd' group. + users.groups.libvirtd.members = builtins.filter (x: builtins.elem "wheel" config.users.users."${x}".extraGroups) (builtins.attrNames config.users.users); +} diff --git a/modules/mealie/default.nix b/modules/mealie/default.nix new file mode 100644 index 0000000..988f0f6 --- /dev/null +++ b/modules/mealie/default.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: +let + domain = "mealie.tdback.net"; + port = 9000; +in +{ + services.mealie = { + enable = true; + package = pkgs.mealie; + listenAddress = "0.0.0.0"; + port = port; + settings = { + BASE_URL = domain; + TZ = "America/Detroit"; + ALLOW_SIGNUP = "false"; + SECURITY_MAX_LOGIN_ATTEMPTS = 3; + DB_ENGINE = "sqlite"; + }; + }; + + services.caddy.virtualHosts."${domain}".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${builtins.toString port} + ''; +} diff --git a/modules/motd/default.nix b/modules/motd/default.nix new file mode 100644 index 0000000..d4afa68 --- /dev/null +++ b/modules/motd/default.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, ... }: +let + motd = + pkgs.writeShellScriptBin "motd" '' + #!/usr/bin/env bash + RED="\e[31m" + GREEN="\e[32m" + YELLOW="\e[33m" + BOLD="\e[1m" + ENDCOLOR="\e[0m" + + case "$(date +'%H')" in + [0-9]|1[0-1]) + TIME="morning" + ;; + 1[2-7]) + TIME="afternoon" + ;; + *) + TIME="evening" + ;; + esac + + UPTIME=$(cat /proc/uptime | cut -f1 -d.) + UPDAYS=$((UPTIME/60/60/24)) + UPHOURS=$((UPTIME/60/60%24)) + UPMINS=$((UPTIME/60%60)) + UPSECS=$((UPTIME%60)) + + MEMORY=$(free -m | awk 'NR == 2 { printf "%s/%sMB (%.2f%%)\n", $3, $2, ($3 * 100) / $2 }') + + SERVICES=$(systemctl list-units | grep -P 'podman-|${lib.strings.concatStringsSep "|" config.motd.servicesToCheck}') + + printf "\n" + printf "''${BOLD}Good $TIME $(whoami), welcome to $(hostname)!$ENDCOLOR\n" + printf "\n" + ${lib.strings.concatStrings (lib.lists.forEach config.motd.networkInterfaces (x: + "printf \"$BOLD * %-20s$ENDCOLOR %s\\n\" \"IPv4 ${x}\" \"$(ip -4 addr show ${x} | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')\"\n" + ))} + printf "$BOLD * %-20s$ENDCOLOR %s\n" "Release" "$(awk -F= '/PRETTY_NAME/ { print $2 }' /etc/os-release | tr -d '"')" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "Kernel" "$(uname -rs)" + printf "\n" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "CPU Usage" "$(awk '{ print $1 ", " $2 ", " $3 }' /proc/loadavg) (1, 5, 15 min)" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "Memory" "$MEMORY" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "System Uptime" "$UPDAYS days $UPHOURS hours $UPMINS minutes $UPSECS seconds" + printf "\n" + + [ -z "$SERVICES" ] && exit + + printf "''${BOLD}Service status:$ENDCOLOR\n" + while IFS= read -r line; do + if [[ ! $line =~ ".service" ]]; then + continue + fi + if echo "$line" | grep -q 'failed'; then + name=$(echo "$line" | awk '{ print $1 }' | sed 's/podman-//g') + printf "$RED• $ENDCOLOR%-50s $RED[failed]$ENDCOLOR\n" "$name" + elif echo "$line" | grep -q 'running'; then + name=$(echo "$line" | awk '{ print $1 }' | sed 's/podman-//g') + printf "$GREEN• $ENDCOLOR%-50s $GREEN[active]$ENDCOLOR\n" "$name" + elif echo "$line" | grep -q 'exited'; then + name=$(echo "$line" | awk '{ print $1 }' | sed 's/podman-//g') + printf "$YELLOW• $ENDCOLOR%-50s $YELLOW[exited]$ENDCOLOR\n" "$name" + else + echo "service status unknown" + fi + done <<< "$SERVICES" + printf "\n" + ''; +in +{ + options.motd = { + networkInterfaces = lib.mkOption { + description = "Network interfaces to monitor."; + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + servicesToCheck = lib.mkOption { + description = "Services to validate alongside podman containers."; + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + }; + + config.environment.systemPackages = [ + motd + ]; +} diff --git a/modules/mumble/default.nix b/modules/mumble/default.nix new file mode 100644 index 0000000..29e3339 --- /dev/null +++ b/modules/mumble/default.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: +{ + services.murmur = { + enable = true; + package = pkgs.murmur; + port = 64738; + openFirewall = true; + environmentFile = "/var/lib/murmur/murmurd.env"; + password = "$MURMURD_PASSWORD"; + }; +} diff --git a/modules/nvidia/default.nix b/modules/nvidia/default.nix new file mode 100644 index 0000000..d8ce9f3 --- /dev/null +++ b/modules/nvidia/default.nix @@ -0,0 +1,24 @@ +{ config, ... }: +{ + hardware.nvidia = { + modesetting.enable = true; + + powerManagement = { + enable = false; + finegrained = false; + }; + + # Don't use the open-source driver! + open = false; + + nvidiaSettings = true; + + # Fix screen tearing. + forceFullCompositionPipeline = true; + + # Optional, but specify version of driver. + package = config.boot.kernelPackages.nvidiaPackages.stable; + }; + + services.xserver.videoDrivers = [ "nvidia" ]; +} diff --git a/modules/pipewire/default.nix b/modules/pipewire/default.nix new file mode 100644 index 0000000..ac70f08 --- /dev/null +++ b/modules/pipewire/default.nix @@ -0,0 +1,13 @@ +{ ... }: +{ + services.pipewire = { + enable = true; + alsa = { + enable = true; + support32Bit = true; + }; + pulse.enable = true; + }; + + security.rtkit.enable = true; +} diff --git a/modules/podman/default.nix b/modules/podman/default.nix new file mode 100644 index 0000000..620e0e3 --- /dev/null +++ b/modules/podman/default.nix @@ -0,0 +1,14 @@ +{ ... }: +{ + virtualisation = { + containers.enable = true; + + podman = { + enable = true; + dockerCompat = true; + defaultNetwork.settings.dns_enabled = true; + }; + + oci-containers.backend = "podman"; + }; +} diff --git a/modules/proxy/default.nix b/modules/proxy/default.nix new file mode 100644 index 0000000..e11beab --- /dev/null +++ b/modules/proxy/default.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: +{ + services.caddy = { + enable = true; + package = pkgs.caddy; + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/modules/pushover/default.nix b/modules/pushover/default.nix new file mode 100644 index 0000000..8c3fd6e --- /dev/null +++ b/modules/pushover/default.nix @@ -0,0 +1,47 @@ +{ config, pkgs, ... }: +let + pushover = + pkgs.writeShellScriptBin "pushover" '' + #!/bin/sh + + die() { echo "$0: $*" >&2; exit 111; } + + APP=$(cat ${config.age.secrets.pushoverAppToken.path}) + USER=$(cat ${config.age.secrets.pushoverUserToken.path}) + + while getopts ":t:" args; do + case "$args" in + t) + TITLE="$OPTARG" + ;; + :) + die "missing option argument for -$OPTARG" + ;; + *) + die "invalid option -$OPTARG" + ;; + esac + done + shift $((OPTIND - 1)) + + MESSAGE="$*" + if [ -z "$MESSAGE" ] || [ "$MESSAGE" = " " ]; then + MESSAGE="No errors to report." + fi + + /run/current-system/sw/bin/curl -s \ + --form-string "token=$APP" \ + --form-string "user=$USER" \ + --form-string "title=$TITLE" \ + --form-string "message=$MESSAGE" \ + https://api.pushover.net/1/messages.json + ''; +in +{ + age.secrets = { + pushoverAppToken.file = ../../secrets/pushoverAppToken.age; + pushoverUserToken.file = ../../secrets/pushoverUserToken.age; + }; + + environment.systemPackages = [ pushover ]; +} diff --git a/modules/searx/default.nix b/modules/searx/default.nix new file mode 100644 index 0000000..b22fb08 --- /dev/null +++ b/modules/searx/default.nix @@ -0,0 +1,37 @@ +{ pkgs, ... }: +let + port = 8888; +in +{ + services.searx = { + enable = true; + package = pkgs.searxng; + environmentFile = "/var/lib/searx/env"; + + settings = { + general = { + debug = false; + instance_name = "searx"; + }; + + search = { + safe_search = 1; + autocomplete = "duckduckgo"; + autocomplete_min = 4; + default_lang = "en-US"; + }; + + server = { + port = port; + bind_address = "0.0.0.0"; + secret_key = "@SEARX_SECRET_KEY@"; + public_instance = false; + image_proxy = true; + }; + + ui.static_use_hash = true; + }; + }; + + networking.firewall.allowedTCPPorts = [ port ]; +} diff --git a/modules/sftpgo/default.nix b/modules/sftpgo/default.nix new file mode 100644 index 0000000..110e556 --- /dev/null +++ b/modules/sftpgo/default.nix @@ -0,0 +1,23 @@ +{ config, pkgs, ... }: +{ + services.sftpgo = { + enable = true; + package = pkgs.sftpgo; + dataDir = "/var/lib/sftpgo"; + + settings = { + httpd.bindings = [{ + port = 8080; + address = "0.0.0.0"; + enable_web_client = true; + enable_web_admin = true; + }]; + }; + }; + + services.caddy.virtualHosts."${config.networking.hostName}.tdback.net".extraConfig = '' + root * /web/client + encode zstd gzip + reverse_proxy http://localhost:8080 + ''; +} diff --git a/modules/ssh/default.nix b/modules/ssh/default.nix new file mode 100644 index 0000000..9c57a43 --- /dev/null +++ b/modules/ssh/default.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + services.openssh = { + enable = true; + startWhenNeeded = true; + ports = [ 2222 ]; + openFirewall = true; + + settings = { + AllowUsers = [ "tdback" ]; + PermitRootLogin = "no"; + PasswordAuthentication = false; + }; + }; +} diff --git a/modules/steam/default.nix b/modules/steam/default.nix new file mode 100644 index 0000000..c8008f9 --- /dev/null +++ b/modules/steam/default.nix @@ -0,0 +1,8 @@ +{ ... }: +{ + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + }; +} diff --git a/modules/vpn/default.nix b/modules/vpn/default.nix new file mode 100644 index 0000000..0482c31 --- /dev/null +++ b/modules/vpn/default.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: +{ + networking.nameservers = [ "9.9.9.9" ]; + + services = { + mullvad-vpn = { + enable = true; + package = pkgs.mullvad-vpn; + }; + + resolved = { + enable = true; + dnssec = "true"; + domains = [ "~." ]; + dnsovertls = "true"; + }; + }; +} diff --git a/modules/wireguard/default.nix b/modules/wireguard/default.nix new file mode 100644 index 0000000..8c25d7a --- /dev/null +++ b/modules/wireguard/default.nix @@ -0,0 +1,15 @@ +{ ... }: +let + port = 51820; +in +{ + networking = { + firewall.allowedUDPPorts = [ port ]; + + wg-quick.interfaces.wg0 = { + autostart = true; + listenPort = port; + configFile = "/etc/wireguard/wg0.conf"; + }; + }; +} diff --git a/modules/wireshark/default.nix b/modules/wireshark/default.nix new file mode 100644 index 0000000..8a7b5e1 --- /dev/null +++ b/modules/wireshark/default.nix @@ -0,0 +1,10 @@ +{ config, pkgs, ... }: +{ + programs.wireshark = { + enable = true; + package = pkgs.wireshark; + }; + + # Add any users in the 'wheel' group to the 'wireshark' group. + users.groups.wireshark.members = builtins.filter (x: builtins.elem "wheel" config.users.users."${x}".extraGroups) (builtins.attrNames config.users.users); +} diff --git a/modules/xonotic/default.nix b/modules/xonotic/default.nix new file mode 100644 index 0000000..3193857 --- /dev/null +++ b/modules/xonotic/default.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: +{ + services.xonotic = { + enable = true; + package = pkgs.xonotic-dedicated; + openFirewall = true; + + settings = { + hostname = "tdback's Xonotic Server"; + net_address = "0.0.0.0"; + port = 26000; + sv_motd = "GLHF! Please report any issues to @tdback on irc.libera.chat"; + + # Specify bots and player count. + maxplayers = 8; + minplayers = 4; + minplayers_per_team = 2; + + # Configure mutators. + g_instagib = 0; + g_grappling_hook = 1; + g_jetpack = 0; + g_vampire = 0; + }; + }; +} diff --git a/modules/zfs/default.nix b/modules/zfs/default.nix new file mode 100644 index 0000000..ae84acb --- /dev/null +++ b/modules/zfs/default.nix @@ -0,0 +1,30 @@ +{ lib, pkgs, ... }: +{ + boot = { + zfs.forceImportRoot = false; + supportedFilesystems.zfs = lib.mkForce true; + }; + + services.zfs = { + autoScrub.enable = true; + zed = { + enableMail = false; + settings = { + ZED_DEBUG_LOG = "/tmp/zed.debug.log"; + ZED_EMAIL_ADDR = [ "root" ]; + ZED_EMAIL_PROG = "/run/current-system/sw/bin/pushover"; + ZED_EMAIL_OPTS = "-t '@SUBJECT@'"; + + ZED_NOTIFY_INTERVAL_SECS = 3600; + ZED_NOTIFY_VERBOSE = true; + + ZED_USE_ENCLOSURE_LEDS = true; + ZED_SCRUB_AFTER_RESILVER = true; + }; + }; + }; + + environment.systemPackages = with pkgs; [ + zfs + ]; +} diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..9240c95 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,9 @@ +{ inputs, ... }: +{ + unstable-packages = final: _prev: { + unstable = import inputs.nixpkgs-unstable { + system = final.system; + config.allowUnfree = true; + }; + }; +} diff --git a/secrets/forgejoAdminPass.age b/secrets/forgejoAdminPass.age new file mode 100644 index 0000000..77c9b7c --- /dev/null +++ b/secrets/forgejoAdminPass.age @@ -0,0 +1,5 @@ +age-encryption.org/v1 +-> ssh-ed25519 D2VkFQ VYS64q2jJv60qTstLLBXbbxvYKBEIKj7QnKY7QGtywg +7el3E+CEIYTmH95IgQRdqnMUex6r43Y6uoDPlvziH0k +--- gEB3j3z5DZ6yFezDvNThc2VexqcCpSWRadAmSOO1ZeI +}~;p8^n d1m:Ħv!^rNU1Chߕ5I>jOY'o= \ No newline at end of file diff --git a/secrets/forgejoRunnerToken.age b/secrets/forgejoRunnerToken.age new file mode 100644 index 0000000..38c4a59 --- /dev/null +++ b/secrets/forgejoRunnerToken.age @@ -0,0 +1,5 @@ +age-encryption.org/v1 +-> ssh-ed25519 D2VkFQ 1MaCGU9sqyvVp6o5UPmkaRQr7R3c3yVkI5kM/TX1YzI +H4KVIaTxR8oENzUMjrajNvMgii6GGosNOQHLbgJ4TDU +--- U74fJ6f4zTLxwkmA95RoQ/bTYOHM4V60C3h+oHQhpB4 +xzr9 ?V`hT-w} ssh-ed25519 gpkhBg 10Q3DBQhRTKVGZ7XeG3lhBnON31TgZdYJci6Nl/GOl8 +eVPcbSg3NxmY8C4L+ua7UZCbxq6ljYEokFph7YMiAxk +-> ssh-ed25519 D2VkFQ 3LslQxpVONPd1ZdKi6c+fzb+90ikkyW2oOXhIpLH6Vo +XiZgDcBCpCXqtdn9s7XVhZUIs+E6P6Xc75NVvMQyVeQ +--- T9rPSC9BUyDqHJEHrq9p5ZpuUpfLKSlkdx4w6bvFZKg +ʆ:f2x っ]k %&1)zn\[) v̺ \ No newline at end of file diff --git a/secrets/pushoverUserToken.age b/secrets/pushoverUserToken.age new file mode 100644 index 0000000..89e9e4d Binary files /dev/null and b/secrets/pushoverUserToken.age differ diff --git a/secrets/secrets.nix b/secrets/secrets.nix new file mode 100644 index 0000000..9906800 --- /dev/null +++ b/secrets/secrets.nix @@ -0,0 +1,13 @@ +let + systems = { + eden = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIByi8x1IgXBC6iw6MJoO7xIkkU4bdIaQ3Mi6zEtm+IJh"; + oasis = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICCvgPNEJrWjeCUmF/izLhIzaAwSNYHW9o5meYmGHGzj"; + }; + allSystems = builtins.attrValues systems; +in +{ + "forgejoAdminPass.age".publicKeys = [ systems.oasis ]; + "forgejoRunnerToken.age".publicKeys = [ systems.oasis ]; + "pushoverAppToken.age".publicKeys = allSystems; + "pushoverUserToken.age".publicKeys = allSystems; +} diff --git a/users/tdback/default.nix b/users/tdback/default.nix new file mode 100644 index 0000000..d9f40d5 --- /dev/null +++ b/users/tdback/default.nix @@ -0,0 +1,21 @@ +{ pkgs, ... }: +{ + users = { + users = { + tdback = { + isNormalUser = true; + uid = 1000; + home = "/home/tdback"; + group = "tdback"; + extraGroups = [ "wheel" "users" "networkmanager" "video" "audio" ]; + shell = pkgs.zsh; + ignoreShellProgramCheck = true; + }; + }; + groups = { + tdback = { + gid = 1000; + }; + }; + }; +} diff --git a/users/tdback/dots.nix b/users/tdback/dots.nix new file mode 100644 index 0000000..cc91d0b --- /dev/null +++ b/users/tdback/dots.nix @@ -0,0 +1,47 @@ +{ config, pkgs, ... }: +{ + home = { + username = "tdback"; + homeDirectory = "/home/tdback"; + stateVersion = "24.05"; + }; + + imports = [ + ../../dots/alacritty + ../../dots/bspwm + ../../dots/desktop + ../../dots/dunst + ../../dots/email + ../../dots/firefox + ../../dots/irc + ../../dots/mpd + ../../dots/ncmpcpp + ../../dots/neomutt + ../../dots/polybar + ../../dots/rofi + ../../dots/sxhkd + ../../dots/tmux + ../../dots/zsh + ./gitconfig.nix + ./packages.nix + ./xdg.nix + ]; + + # Generate X11 init scripts. + home.file = { + ".xinitrc".text = '' + [ -f ~/.xprofile ] && . ~/.xprofile + [ -f ~/.Xresources ] && xrdb -merge ~/.Xresources + exec bspwm + ''; + ".xprofile".text = '' + xrandr --output DP-0 --primary --mode 1920x1080 --rotate normal --rate 165 + ''; + ".Xresources".text = '' + Xcursor.size: 24 + ''; + }; + + # Let home manager install and manage itself. + programs.home-manager.enable = true; +} diff --git a/users/tdback/gitconfig.nix b/users/tdback/gitconfig.nix new file mode 100644 index 0000000..1ef4c6e --- /dev/null +++ b/users/tdback/gitconfig.nix @@ -0,0 +1,8 @@ +{ + programs.git = { + enable = true; + userName = "tdback"; + userEmail = "tyler@tdback.net"; + extraConfig.init.defaultBranch = "main"; + }; +} diff --git a/users/tdback/packages.nix b/users/tdback/packages.nix new file mode 100644 index 0000000..c663468 --- /dev/null +++ b/users/tdback/packages.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: +{ + home.packages = with pkgs.unstable; [ + age + bat + clang + croc + dig + fd + feh + (ffmpeg.override { withXcb = true; }) + flameshot + fzf + gimp + gitu + jq + mpc-cli + mpv + neovim + nixd + pavucontrol + pamixer + pciutils + ripgrep + signal-desktop + sxiv + tealdeer + unzip + xclip + yt-dlp + zathura + zip + ]; +} diff --git a/users/tdback/xdg.nix b/users/tdback/xdg.nix new file mode 100644 index 0000000..9b49fde --- /dev/null +++ b/users/tdback/xdg.nix @@ -0,0 +1,29 @@ +{ config, ... }: +let + dirs = [ + "desktop" + "documents" + "download" + "music" + "pictures" + "publicShare" + "templates" + "videos" + ]; + + defined = { + "documents" = "${config.home.homeDirectory}/documents"; + "download" = "${config.home.homeDirectory}/downloads"; + }; + + userDirs = builtins.map (dir: { name = dir; value = defined.${dir} or null; }) dirs; +in +{ + xdg = { + enable = true; + userDirs = { + enable = true; + createDirectories = true; + } // builtins.listToAttrs userDirs; + }; +}