Compare commits

...
Author SHA1 Message Date
Nexoniarz
f1f5f71245 SSH between my machines and ZeroVRAM's port, home network only; host names nexo-pc / nexo-laptop
- modules/remote.nix: OpenSSH with keys only (no passwords, no root), ports 22 and
  8080 (zvm_node) opened for 192.168.1.0/24 only; /etc/hosts names for both machines
  (DNS goes over TLS, so the router's *.lan names don't resolve)
- the laptop accepts the PC's key; the PC's list is ready for the laptop's
- hostName: nixos -> nexo-laptop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 18:39:59 +01:00
Nexoniarz
999b49800d Revert "Firefox: DNS-over-HTTPS through Quad9"
Back to trr.mode 5: systemd-resolved already encrypts DNS (DNS-over-TLS
to Cloudflare and Quad9), so Firefox doesn't need its own DoH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 12:20:41 +01:00
Nexoniarz
466df890c4 Firefox: DNS-over-HTTPS through Quad9
network.trr.mode 2 with dns.quad9.net: DoH first, falling back to the
system resolver (systemd-resolved over DNS-over-TLS), so lookups stay
encrypted either way. Mode 5 had turned Firefox's DoH off entirely.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 12:19:13 +01:00
Nexoniarz
bc190454b6 Bring over the PC config's changes: NexoPass, AppImages, Firefox privacy
- nexopass and nexopass-gui (scripts.nix, with the wordlist and icon)
- AppImages run directly through appimage-run's binfmt (apps.nix)
- Firefox: full fingerprinting protection except forced light mode,
  Accept-Language en-US, and its own font list without corefonts
- README updated to match

Left out as PC-only: OpenRGB, acpi_enforce_resources=lax, the
Vega 8/RTX 3060 Ti graphics setup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 12:09:39 +01:00
Nexoniarz
863abb4fd3 Switch to the PC config layout: Plasma, Limine, shared configs/
Same modules and settings as nexoniarz-config-nixos; only hardware.nix
differs. Pantheon/LightDM -> Plasma 6/SDDM, systemd-boot -> Limine,
system.nix/drivers.nix split into focused modules, Firefox prefs and
fastfetch config in configs/.

Laptop hardware kept: AMD 680M + RTX 4050 PRIME offload (bus IDs
unchanged), NVIDIA suspend fix, asusd + supergfxd, tablet driver,
DualSense ERTM fix, laptop scripts (brightness, hotspot, telemetry,
weather). Dropped: GoPro v4l2loopback webcam, blueman.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 21:07:55 +02:00
25 changed files with 10058 additions and 368 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.claude
result
result-*

View file

@ -1,36 +1,52 @@
# nexoniarz-config-nixos-laptop
My personal NixOS system configuration tailored for daily use on an
**ASUS TUF Gaming A15 (FA507NU)**.
My personal NixOS configuration for an ASUS TUF Gaming A15 (FA507NU).
Shares its layout and settings with my PC config
([nexoniarz-config-nixos](https://github.com/Nexoniarz/nexoniarz-config-nixos));
only the hardware differs.
## Overview
- **OS:** NixOS
- **DE / Compositor:** Pantheon (gala, Wayland)
- **Display manager:** LightDM (elementary greeter)
- **OS:** NixOS 26.05 (unstable channel)
- **Desktop:** KDE Plasma 6 on Wayland (KWin), SDDM
- **Bootloader:** Limine
- **Terminal:** Konsole
- **Shell:** Zsh
- **Audio:** PipeWire
- **CPU:** AMD Ryzen 5 7535HS
- **GPU:** AMD Radeon 680M (iGPU, drives the internal panel) + NVIDIA RTX
4050 Max-Q (dGPU, PRIME render offload only — run anything through it with
`nvidia-offload <command>`)
- **Laptop control:** `asusctl` (fan curves, keyboard backlight, battery
charge limit) + `supergfxctl` (dGPU power-state switching)
- **GPU:** AMD Radeon 680M (iGPU, drives the panel) + NVIDIA RTX 4050 Max-Q
(PRIME render offload only; run things on it with `nvidia-offload <command>`)
- **Laptop control:** asusctl (fans, keyboard backlight, charge limit) + supergfxctl (dGPU power state)
## Layout
- `configuration.nix` — top-level imports
- `hardware-configuration.nix` — generated by `nixos-generate-config`, don't
hand-edit
- `modules/system.nix` — bootloader, networking, time, sound, hardening,
nix-ld
- `modules/drivers.nix` — hybrid graphics (NVIDIA PRIME offload), ASUS
daemons, misc hardware (webcam loopback, tablet driver)
- `modules/desktop.nix` — Pantheon desktop environment
- `modules/users.nix` — user account, Steam, Firefox, Flatpak
- `modules/apps.nix` — all installed packages
- `modules/scripts.nix` + `modules/scripts/` — small custom CLI helpers
(encrypted vault toggle, metadata stripping, brightness control, Wi-Fi
hotspot, system telemetry, weather fetch)
| File | Contents |
|---|---|
| `configuration.nix` | Imports only |
| `modules/boot.nix` | Limine, kernel, zram/swap |
| `modules/networking.nix` | NetworkManager, firewall, DNS-over-TLS, MAC randomization |
| `modules/locale.nix` | Timezone, locale, console keymap |
| `modules/nix-settings.nix` | Nix features, GC, unfree |
| `modules/security.nix` | sysctl hardening, sudo, firejail, GnuPG, polkit |
| `modules/remote.nix` | SSH between my machines (keys only) and ZeroVRAM's port 8080, both for the home network only; fixed host names `nexo-pc` / `nexo-laptop` |
| `modules/hardware.nix` | Hybrid graphics (PRIME offload), ASUS daemons, tablet, Bluetooth, I2C, RTL-SDR, printing |
| `modules/audio.nix` | PipeWire |
| `modules/desktop.nix` | Plasma, SDDM, fonts, theming |
| `modules/users.nix` | Account, shell, Steam, Flatpak |
| `modules/apps.nix` | Installed packages, nix-ld, AppImage support |
| `modules/default-apps.nix` | MIME associations |
| `modules/scripts.nix` | Custom scripts in `modules/scripts/` (vault, metadata stripping, brightness, Wi-Fi hotspot, telemetry, weather, NexoPass) |
| `modules/fastfetch.nix` | Installs `configs/fastfetch/config.jsonc` system-wide |
| `modules/firefox.nix` | Firefox, with prefs from `configs/firefox/prefs.js` (reapplied each start, not locked), and its own font list without the Microsoft core fonts (against font fingerprinting) |
| `configs/` | Plain app config files (Firefox prefs, fastfetch) used by the modules |
## NexoPass
`nexopass` (in `modules/scripts/`) derives site passwords from a master with Argon2id, so no password is ever stored. You can have several accounts, each with its own master and an encrypted site list (current versions plus an archive of old ones) in `~/.local/share/nexopass/accounts/`. One app password or PIN unlocks them all; a master is only typed to create or recover an account.
Passwords of 5-15 words or 12-64 characters, "did you mean" for typos, "stay unlocked" for a few minutes (kernel keyring), encrypted export/import shared with the NexoPass Android app, and `nexopass settings`. Run `nexopass help` for everything else. Apache License 2.0.
`nexopass-gui` is the [NexoPass](https://github.com/Nexoniarz/NexoPass) window (also on Android and Windows), fetched from its GitHub release. It uses the same files as `nexopass`, so both see the same accounts and app password.
---

View file

@ -0,0 +1,80 @@
// Gruvbox-themed fastfetch, matching the Limine and icon theme.
// Colors: yellow fabd2f, aqua 8ec07c, blue 83a598, orange fe8019, gray 928374.
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"source": "nixos",
"color": {
"1": "38;2;131;165;152",
"2": "38;2;142;192;124",
"3": "38;2;131;165;152",
"4": "38;2;142;192;124",
"5": "38;2;131;165;152",
"6": "38;2;142;192;124"
},
"padding": { "top": 1, "left": 1, "right": 3 }
},
"display": {
"separator": " ",
"color": {
"keys": "38;2;250;189;47",
"title": "38;2;254;128;25",
"output": "38;2;235;219;178"
},
"key": { "width": 13 },
"bar": {
"char": { "elapsed": "■", "total": "■" },
"border": { "left": "", "right": "" },
"color": { "total": "38;2;80;73;69" },
"width": 12
},
"percent": {
"type": ["num", "bar"],
"color": {
"green": "38;2;184;187;38",
"yellow": "38;2;250;189;47",
"red": "38;2;251;73;52"
}
},
"size": { "binaryPrefix": "iec", "ndigits": 1 }
},
"modules": [
{
"type": "title",
"format": "{#1}󱄅 {#38;2;254;128;25}{user-name}{#38;2;146;131;116}@{#38;2;142;192;124}{host-name}"
},
{
"type": "custom",
"format": "{#38;2;146;131;116}╭─────────────── {#38;2;131;165;152}system{#38;2;146;131;116} ───────────────"
},
{ "type": "os", "key": "│ 󱄅 os", "keyColor": "38;2;131;165;152", "format": "{pretty-name}" },
{ "type": "kernel", "key": "│ 󰌽 kernel", "keyColor": "38;2;131;165;152" },
{ "type": "packages", "key": "│ 󰏖 pkgs", "keyColor": "38;2;131;165;152", "format": "{nix-system} sys · {nix-user} user · {flatpak-all} flatpak" },
{ "type": "uptime", "key": "│ 󰔟 uptime", "keyColor": "38;2;131;165;152" },
{ "type": "shell", "key": "│ 󰆍 shell", "keyColor": "38;2;131;165;152" },
{
"type": "custom",
"format": "{#38;2;146;131;116}├─────────────── {#38;2;142;192;124}desktop{#38;2;146;131;116} ──────────────"
},
{ "type": "de", "key": "│ 󰕮 de", "keyColor": "38;2;142;192;124" },
{ "type": "wm", "key": "│ 󰖲 wm", "keyColor": "38;2;142;192;124" },
{ "type": "icons", "key": "│ 󰀻 icons", "keyColor": "38;2;142;192;124", "format": "{1}" },
{ "type": "cursor", "key": "│ 󰇀 cursor", "keyColor": "38;2;142;192;124" },
{
"type": "custom",
"format": "{#38;2;146;131;116}├─────────────── {#38;2;254;128;25}hardware{#38;2;146;131;116} ─────────────"
},
{ "type": "host", "key": "│ 󰍹 board", "keyColor": "38;2;254;128;25" },
{ "type": "cpu", "key": "│ 󰻠 cpu", "keyColor": "38;2;254;128;25", "temp": true, "format": "{name} ({cores-logical}) @ {freq-max}" },
{ "type": "gpu", "key": "│ 󰢮 gpu", "keyColor": "38;2;254;128;25", "format": "{name}" },
{ "type": "display", "key": "│ 󰍺 display","keyColor": "38;2;254;128;25", "format": "{width}x{height} @ {refresh-rate} Hz" },
{ "type": "memory", "key": "│ 󰑭 ram", "keyColor": "38;2;254;128;25", "format": "{percentage-bar} {used} / {total} ({percentage})" },
{ "type": "disk", "key": "│ 󰋊 disk", "keyColor": "38;2;254;128;25", "folders": "/", "format": "{size-percentage-bar} {size-used} / {size-total} ({size-percentage})" },
{
"type": "custom",
"format": "{#38;2;146;131;116}╰──────────────────────────────────────────"
},
"break",
{ "type": "colors", "symbol": "circle", "paddingLeft": 2 }
]
}

147
configs/firefox/prefs.js Normal file
View file

@ -0,0 +1,147 @@
// Nexoniarz's Firefox prefs (Firefox 157, "Nova" design)
//
// Loaded by NixOS (modules/firefox.nix) into Firefox's autoconfig. pref()
// sets the value on every Firefox start but doesn't lock it: you can still
// change things in Settings/about:config, they just reset on next start.
// To change a setting permanently, edit it here and nixos-rebuild.
// To stop managing a setting, delete its line (Firefox then keeps
// whatever value it last had).
//
// GPU video decoding also needs env vars set in modules/hardware.nix:
// LIBVA_DRIVER_NAME=nvidia NVD_BACKEND=direct MOZ_DISABLE_RDD_SANDBOX=1
/*** PRIVACY: tracking & fingerprinting ***/
// Strict Enhanced Tracking Protection: blocks trackers, cryptominers and
// known fingerprinters, isolates cookies per site (Total Cookie Protection),
// strips tracking parameters from URLs, and turns on fingerprintingProtection
// (randomized canvas, fewer exposed hardware details).
// If a site breaks: click the shield in the address bar and turn it off
// for that site only.
pref("browser.contentblocking.category", "strict");
// Fingerprinting protection at full strength: everything resistFingerprinting
// does (a Windows user agent and platform that agree, UTC time, a fixed core
// count, the bundled font list, no precise GPU name, canvas noise...), but
// switched on through fingerprintingProtection, because only that one takes
// exceptions. The one exception: prefers-color-scheme isn't forced to light,
// so sites still get dark mode.
// To check it worked: coveryourtracks.eff.org should show Windows in both
// User Agent and Platform, and timezone UTC.
pref("privacy.resistFingerprinting", false);
pref("privacy.fingerprintingProtection", true);
pref("privacy.fingerprintingProtection.pbmode", true);
pref("privacy.fingerprintingProtection.overrides", "+AllTargets,-CSSPrefersColorScheme");
// Ask sites for English pages the way most English-speaking browsers do
// (en-US, en), so the language header doesn't stand out. en-GB would be
// rarer, and rarer is what gets you tracked.
pref("intl.accept_languages", "en-US, en");
pref("privacy.spoof_english", 2);
// Sites only see base system fonts, not the ones installed on top
// (the Microsoft core fonts made the font list 1 in 9,481).
pref("layout.css.font-visibility.standard", 1);
pref("layout.css.font-visibility.trackingprotection", 1);
pref("layout.css.font-visibility.private", 1);
pref("layout.css.font-visibility.resistFingerprinting", 1);
// WebGPU tells sites about the graphics card in detail. Off breaks some
// sites (3D, AI demos, some games); uncomment to turn it off.
// pref("dom.webgpu.enabled", false);
// First-party isolation stays ON. Every existing cookie in this profile was
// saved with a first-party tag; turning this off makes Firefox ignore them
// all (logged out everywhere). Works alongside Strict mode.
pref("privacy.firstparty.isolate", true);
// Cross-site requests only send the origin (https://site.com/), not the
// full page URL you came from.
pref("network.http.referer.XOriginTrimmingPolicy", 2);
// Tell sites not to sell/share your data (legally binding in some places).
pref("privacy.globalprivacycontrol.enabled", true);
// No WebRTC: stops IP leaks. Web video calls (Meet, Discord in-browser)
// need this set to true.
pref("media.peerconnection.enabled", false);
/*** PRIVACY: Mozilla data collection ***/
pref("datareporting.healthreport.uploadEnabled", false);
pref("datareporting.policy.dataSubmissionEnabled", false);
pref("datareporting.usage.uploadEnabled", false);
pref("toolkit.telemetry.enabled", false);
pref("toolkit.telemetry.unified", false);
pref("app.shield.optoutstudies.enabled", false);
pref("app.normandy.enabled", false);
pref("nimbus.rollouts.enabled", false);
pref("browser.discovery.enabled", false);
// Firefox Suggest launched in Poland with Firefox 157; it adds sponsored
// results to the address bar.
pref("browser.urlbar.quicksuggest.enabled", false);
pref("browser.urlbar.suggest.quicksuggest.sponsored", false);
pref("browser.urlbar.suggest.quicksuggest.nonsponsored", false);
pref("browser.newtabpage.activity-stream.showSponsored", false);
pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false);
/*** SECURITY ***/
// HTTPS-Only: upgrade every site to HTTPS and warn before loading plain
// HTTP. Was enabled once, but it's off now.
pref("dom.security.https_only_mode", true);
// Safe Browsing back on for malware/phishing. It checks a local list and
// only sends a partial hash when a URL matches, never your history.
// The remote download check (which uploads file metadata to Google) stays off.
pref("browser.safebrowsing.malware.enabled", true);
pref("browser.safebrowsing.phishing.enabled", true);
pref("browser.safebrowsing.downloads.enabled", true);
pref("browser.safebrowsing.downloads.remote.enabled", false);
/*** NETWORK ***/
// DNS: use the system resolver (systemd-resolved with DNS-over-TLS) and
// never let Firefox switch itself to its own DNS-over-HTTPS provider.
pref("network.trr.mode", 5);
// No preloading pages or DNS you didn't ask for.
pref("network.dns.disablePrefetch", true);
pref("network.prefetch-next", false);
pref("network.http.speculative-parallel-limit", 0);
pref("browser.urlbar.speculativeConnect.enabled", false);
pref("network.captive-portal-service.enabled", false);
pref("network.connectivity-service.enabled", false);
/*** GPU VIDEO DECODING (RTX 3060 Ti, nvidia-vaapi-driver) ***/
// Firefox blocklists VA-API on NVIDIA; force it on. The 3060 Ti decodes
// H.264, VP9 and AV1 in hardware. (media.ffmpeg.vaapi.enabled is gone
// since Firefox 137; this pref replaced it.)
pref("media.hardware-video-decoding.force-enabled", true);
pref("media.rdd-ffmpeg.enabled", true);
pref("gfx.webrender.all", true);
/*** LOOK & FEEL ***/
// Compact mode (back in Firefox 157): thinner tabs and toolbars.
// Switch back via ☰ > More tools > Customize toolbar > Density.
pref("browser.compactmode.show", true);
pref("browser.uidensity", 1);
// Smoother, momentum-based scrolling, nicer at 240 Hz.
pref("general.smoothScroll.msdPhysics.enabled", true);
// Middle-click on a page to autoscroll (like on Windows).
pref("general.autoScroll", true);
// Closing the last tab doesn't close the window.
pref("browser.tabs.closeWindowWithLastTab", false);
// Show the full URL including https:// so you always see what site you're on.
pref("browser.urlbar.trimHttps", false);
pref("browser.urlbar.trimURLs", false);
// No "proceed with caution" page every time you open about:config.
pref("browser.aboutConfig.showWarning", false);

View file

@ -1,18 +1,31 @@
# Main NixOS configuration file importing modular configurations.
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix # Generated hardware scan results
./modules/system.nix # Bootloader, networking, time, sound, hardening, nix-ld
./modules/drivers.nix # AMD/NVIDIA hybrid graphics (PRIME) and ASUS laptop control
./modules/desktop.nix # Pantheon desktop environment (LightDM + gala)
./modules/users.nix # User accounts and global configurations
./modules/apps.nix # All installed packages: apps, CLI tools, dev toolchains
./modules/scripts.nix # Custom system scripts and helpers
./hardware-configuration.nix
# Core system
./modules/boot.nix
./modules/networking.nix
./modules/locale.nix
./modules/nix-settings.nix
./modules/security.nix
./modules/remote.nix
# Hardware
./modules/hardware.nix
./modules/audio.nix
# Desktop & user
./modules/desktop.nix
./modules/users.nix
./modules/apps.nix
./modules/default-apps.nix
./modules/scripts.nix
./modules/fastfetch.nix
./modules/firefox.nix
];
# Do not change this value. Read documentation before updating.
system.stateVersion = "26.05";
system.stateVersion = "26.05";
}

View file

@ -1,16 +1,46 @@
{ config, pkgs, ... }:
let
# Both SDR++ and rtl_433 default to supporting every radio ever made, which
# drags in UHD (USRP firmware), BladeRF and LimeSuite — ~1.5 GB for
# hardware we don't own. These two overrides cut that down to the RTL-SDR paths.
soapysdrLean = pkgs.soapysdr.override {
extraPackages = with pkgs; [
soapyrtlsdr
soapyremote
];
};
rtl433Lean = pkgs.rtl_433.override {
soapysdr-with-plugins = soapysdrLean;
};
# Leaves the RTL-SDR, rtl_tcp, file and network sources on.
sdrppLean = pkgs.sdrpp.override {
soapy_source = false;
bladerf_source = false;
limesdr_source = false;
plutosdr_source = false;
airspy_source = false;
airspyhf_source = false;
hermes_source = false;
rfspace_source = false;
dragonlabs_source = false;
spectran_http_source = false;
};
in
{
# Every installed package — GUI apps, CLI tools, and dev toolchains alike.
# If it's "install X", it goes here.
users.users."nexoniarz".packages = with pkgs; [
# Hardware control (Pantheon itself ships Files/Terminal/Screenshot/
# notifications/dock/launcher — see services.desktopManager.pantheon
# in modules/desktop.nix, nothing to list here for those)
brightnessctl # Backlight brightness (internal laptop panel)
ddcutil # DDC/CI brightness (external monitors)
lm_sensors # sensors-detect helps ddcutil find I2C buses; also feeds asusctl
tumbler
brightnessctl
ddcutil
lm_sensors
networkmanager # nmcli, for the Wi-Fi hotspot script
xdg-user-dirs
# Apps
blender
@ -22,35 +52,79 @@
vlc
filezilla
chromium
obs-studio
sdrppLean
rtl433Lean
lmms
krita
# Games
prismlauncher
pkgs.osu-lazer-bin
osu-lazer-bin
# Dev: compilers, runtimes, languages
# Dev
glibc
musl
cmake
gnumake # Provides the 'make' command
gnumake
gcc
python3
openjdk25
claude-code # AI Developer Assistant
go
claude-code
codex
];
# Global command-line utilities available everywhere
environment.systemPackages = with pkgs; [
git
gh # GitHub CLI — was only installed ad-hoc before (login didn't survive)
gh
vim
fastfetch
gparted
efibootmgr
firejail
gnupg
lmstudio
kdePackages.ark
p7zip
unzip
unrar
libreoffice # GTK3 build — matches Pantheon's native GTK theming, unlike the Qt build
kdePackages.gwenview
kdePackages.kate
kdePackages.qqc2-desktop-style
linphonePackages.linphone-desktop
kdePackages.kcalc
kdePackages.okular
kdePackages.elisa
kdePackages.konsole
kdePackages.dolphin
kdePackages.plasma-systemmonitor
kdePackages.kdialog
qt5.qtwayland
qt6.qtwayland
qemu
file
wineWow64Packages.stable
ghidra
jdk
python3
radare2
binwalk
];
# Lets non-Nix binaries (e.g. the Tor Browser bundle) find an FHS linker.
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
glib gtk3 gdk-pixbuf pango cairo atk
dbus dbus-glib fontconfig freetype
libx11 libxext libxrender libxtst
libxi libxcomposite libxdamage libxfixes
libxrandr libxcursor libxcb libxkbcommon
alsa-lib mesa zlib stdenv.cc.cc
];
# Registers AppImages with binfmt_misc, so ./Foo.AppImage (or a double-click
# in Dolphin) runs straight through appimage-run's FHS environment.
programs.appimage.enable = true;
programs.appimage.binfmt = true;
}

25
modules/audio.nix Normal file
View file

@ -0,0 +1,25 @@
{ config, pkgs, ... }:
{
security.rtkit.enable = true;
services.pulseaudio.enable = false;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# Bluetooth headphones are playback-only here (mic comes from the USB
# codec). Disable HSP/HFP so they never drop to 8/16 kHz mono call mode.
wireplumber.extraConfig."11-bluetooth-policy" = {
"wireplumber.settings" = {
"bluetooth.autoswitch-to-headset-profile" = false;
};
"monitor.bluez.properties" = {
# PC only sends audio. Allowing a2dp_sink lets the Monitor II (which
# also advertises an A2DP source) connect backwards as "audio gateway".
"bluez5.roles" = [ "a2dp_source" ];
};
};
};
}

39
modules/boot.nix Normal file
View file

@ -0,0 +1,39 @@
{ config, lib, pkgs, ... }:
{
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.limine = {
enable = true;
maxGenerations = 5;
# Gruvbox, to match the icon theme.
style = {
wallpapers = [ ]; # Solid background; a path here would be used instead
interface = {
branding = "NixOS";
brandingColor = "fabd2f";
helpColor = "928374";
helpColorBright = "d79921";
};
graphicalTerminal = {
foreground = "ebdbb2";
background = "00282828";
brightForeground = "fbf1c7";
palette = "282828;cc241d;98971a;d79921;458588;b16286;689d6a;a89984";
brightPalette = "928374;fb4934;b8bb26;fabd2f;83a598;d3869b;8ec07c;ebdbb2";
margin = 32;
};
};
};
boot.kernelPackages = pkgs.linuxPackages;
boot.supportedFilesystems = [ "fuse" ];
programs.fuse.userAllowOther = true;
# zram instead of disk swap: nothing sensitive is written to disk in
# plaintext. systemd's gpt-auto-generator would otherwise re-activate the
# old swap partition regardless of swapDevices, hence the kernel param.
zramSwap.enable = true;
swapDevices = lib.mkForce [ ];
boot.kernelParams = [ "systemd.gpt_auto=0" ];
}

80
modules/default-apps.nix Normal file
View file

@ -0,0 +1,80 @@
{ config, pkgs, lib, ... }:
{
environment.systemPackages = with pkgs; [
libreoffice-qt6
];
# GIO picks the terminal from here for "Open Terminal" style actions.
environment.etc."xdg/xdg-terminals.list".text = ''
org.kde.konsole.desktop
'';
# System-level fallbacks. Per the XDG spec these are only consulted for a
# mimetype the user's own ~/.config/mimeapps.list doesn't already claim,
# so any "Open With" choice you make later still wins over this.
#
# One mimetype=desktopfile pair per line. The semicolon only separates
# multiple candidates for the SAME key — it does not chain separate pairs,
# and parsers match by scanning for a line starting with "mimetype=", so
# cramming several onto one line silently hides all but the first.
environment.etc."xdg/mimeapps.list".text =
let
gwenviewMimes = [
"image/avif" "image/gif" "image/heif" "image/jpeg"
"image/jxl" "image/png" "image/bmp" "image/x-eps" "image/x-icns"
"image/x-ico" "image/x-portable-bitmap" "image/x-portable-graymap"
"image/x-portable-pixmap" "image/x-xbitmap" "image/x-xpixmap"
"image/tiff" "image/x-psd" "image/x-webp" "image/webp" "image/x-tga"
"image/x-xcf" "image/openraster" "image/svg+xml" "image/svg+xml-compressed"
];
arkMimes = [
"application/x-cd-image" "application/x-bcpio" "application/x-cpio"
"application/x-cpio-compressed" "application/x-rpm" "application/x-compress"
"application/gzip" "application/x-bzip" "application/x-bzip2"
"application/x-lzma" "application/x-xz" "application/zstd" "application/x-lz4"
"application/x-source-rpm" "application/vnd.debian.binary-package"
"application/vnd.ms-cab-compressed" "application/x-archive" "application/x-tar"
"application/x-compressed-tar" "application/x-bzip-compressed-tar"
"application/x-bzip2-compressed-tar" "application/x-tarz"
"application/x-xz-compressed-tar" "application/x-lzma-compressed-tar"
"application/x-7z-compressed" "application/vnd.rar" "application/zip"
"application/x-java-archive" "application/x-arj"
];
okularMimes = [
"application/pdf" "application/x-pdf" "image/vnd.djvu" "application/epub+zip"
"application/x-fictionbook+xml" "application/x-mobipocket-ebook"
"image/x-portable-document" "application/x-cbr" "application/x-cbz"
"application/x-cbt" "application/x-cb7" "application/postscript"
];
vlcMimes = [
"video/mp4" "video/x-matroska" "video/webm" "video/x-msvideo"
"video/quicktime" "video/mpeg" "video/x-ms-wmv" "video/x-flv"
"video/3gpp" "video/ogg" "video/x-theora+ogg" "video/x-ogm+ogg"
"application/x-matroska" "application/vnd.rn-realmedia"
];
elisaMimes = [
"audio/mpeg" "audio/flac" "audio/x-flac" "audio/ogg" "audio/x-vorbis+ogg"
"audio/opus" "audio/x-opus+ogg" "audio/mp4" "audio/aac" "audio/x-wav"
"audio/wav" "audio/x-ms-wma" "audio/x-aiff" "audio/x-musepack"
];
kateMimes = [
"text/plain" "text/markdown" "text/x-csrc" "text/x-c++src" "text/x-chdr"
"text/x-c++hdr" "text/x-python" "text/x-java" "text/x-shellscript"
"text/x-nix" "text/css" "text/html" "text/xml" "application/json"
"application/x-yaml" "application/toml" "application/javascript"
"application/x-shellscript" "text/x-log"
];
line = desktop: mime: "${mime}=${desktop}";
in
''
[Default Applications]
inode/directory=org.kde.dolphin.desktop
${lib.concatMapStringsSep "\n" (line "org.kde.gwenview.desktop") gwenviewMimes}
${lib.concatMapStringsSep "\n" (line "org.kde.ark.desktop") arkMimes}
${lib.concatMapStringsSep "\n" (line "org.kde.okular.desktop") okularMimes}
${lib.concatMapStringsSep "\n" (line "vlc.desktop") vlcMimes}
${lib.concatMapStringsSep "\n" (line "org.kde.elisa.desktop") elisaMimes}
${lib.concatMapStringsSep "\n" (line "org.kde.kate.desktop") kateMimes}
'';
}

View file

@ -1,38 +1,72 @@
{ config, pkgs, ... }:
{
# --- Pantheon: elementary OS's desktop environment (gala compositor, Wayland) ---
# Pulls in its own session (pantheon-wayland), top panel (Wingpanel), dock,
# app launcher, Files, Terminal, Screenshot, Photos, notifications, and
# GTK/icon theming — no separate compositor config or dotfile symlinking
# needed, unlike the previous Hyprland setup.
# Plasma ships a proper Wayland session (KWin) with solid Xwayland
# support; xserver stays on for that Xwayland layer and for the xkb
# layout below, not because the session itself needs it.
services.xserver.enable = true;
services.xserver.displayManager.lightdm.enable = true;
services.desktopManager.pantheon.enable = true;
services.desktopManager.plasma6.enable = true;
# SDDM is KDE's own greeter — Qt-based, and launches Wayland sessions
# natively, Plasma included.
services.displayManager.sddm = {
enable = true;
wayland.enable = true;
};
# Keyboard layout for LightDM/XWayland; Pantheon's own session picks this
# up too.
services.xserver.xkb = {
layout = "pl";
variant = "";
};
security.polkit.enable = true;
services.tumbler.enable = true;
services.gvfs.enable = true;
# Native Wayland backend for Electron/Chromium-based apps
environment.sessionVariables.NIXOS_OZONE_WL = "1";
# xserver.nix installs xterm unconditionally; Konsole is the terminal here.
services.xserver.excludePackages = [ pkgs.xterm ];
# Comfortable trackpad defaults for a laptop — tap-to-click and natural
# scrolling aren't on by default, and gala reads touchpad settings from
# GSettings at runtime (not services.libinput, which is X11-only), so
# they're set here as a dconf default instead.
programs.dconf.profiles.user.databases = [
{
settings."org/gnome/desktop/peripherals/touchpad" = {
tap-to-click = true;
natural-scroll = true;
two-finger-scrolling-enabled = true;
};
}
# Icon/cursor theme packages. Plasma has no gsettings-style declarative
# knob for this the way Budgie did — pick them in System Settings, or
# bring in plasma-manager later for a fully declarative setup.
environment.systemPackages = [
pkgs.gruvbox-plus-icons
pkgs.bibata-cursors
];
# The third-party "Bouncing Popups" KWin effect (~/.local/share/kwin/effects)
# stacks on top of Plasma's own slidingpopups/fadingpopups and forces blur
# on every popup and the panel, making applet popups and panel settings
# open sluggishly. [$i] locks the key so ~/.config/kwinrc can't re-enable it.
environment.etc."xdg/kwinrc".text = ''
[Plugins]
bouncingPopupsEnabled[$i]=false
'';
# Breeze Dark as the default Plasma (panel/popup) theme. Avoid sparse
# third-party themes like "Darkly" (18 files): every SVG they lack falls
# back via an uncached search of all ~89 XDG_DATA_DIRS, which made applet
# popups and panel settings take 2-6 s to open. Not locked, so the theme
# can still be changed in System Settings.
environment.etc."xdg/plasmarc".text = ''
[Theme]
name=breeze-dark
'';
environment.extraInit = ''
export XDG_DATA_DIRS="$XDG_DATA_DIRS:${pkgs.gtk3}/share/gsettings-schemas/${pkgs.gtk3.name}"
'';
fonts.packages = with pkgs; [
corefonts
dejavu_fonts
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
nerd-fonts.fira-code
nerd-fonts.jetbrains-mono
nerd-fonts.hack
inter
liberation_ttf
roboto
];
}

View file

@ -1,79 +0,0 @@
{ config, lib, pkgs, ... }:
{
# Enable graphics driver support and 32-bit acceleration (for Steam/gaming)
hardware.graphics = {
enable = true;
enable32Bit = true;
};
#OpenTabletDriver
hardware.opentabletdriver.enable = true;
hardware.uinput.enable = true;
boot.kernelModules = [ "uinput" "v4l2loopback" ];
# Virtual webcam device so ffmpeg (fed by the GoPro's stream) can appear
# as a normal camera to apps like Discord. exclusive_caps=1 is required
# for Chromium/WebRTC-based apps to recognize it as a real capture device.
boot.extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ];
boot.extraModprobeConfig = ''
options v4l2loopback devices=1 video_nr=10 card_label="GoPro Webcam" exclusive_caps=1
# PS4/PS5 controllers (e.g. DualSense) connect over Bluetooth then
# immediately disconnect — a well-known Linux Bluetooth stack issue
# where many adapters' Enhanced Retransmission Mode implementation is
# broken. Disabling ERTM is the standard, widely-documented fix.
options bluetooth disable_ertm=1
'';
# I2C bus, for DDC/CI monitor control (brightness) via ddcutil, when
# driving an external monitor over DisplayPort/HDMI. The internal panel
# uses the kernel backlight class instead (brightness-ctl picks whichever
# applies — see modules/scripts/brightness-ctl.sh).
hardware.i2c.enable = true;
# --- Hybrid graphics: AMD Radeon 680M (iGPU, drives the internal panel)
# + NVIDIA RTX 4050 Max-Q (dGPU, offload-only) — ASUS TUF Gaming A15
# FA507NU. Bus IDs come straight from `lspci` on this machine, not
# guessed: 01:00.0 (NVIDIA) -> PCI:1:0:0, 35:00.0 (AMD) -> PCI:53:0:0.
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia = {
# Required settings
modesetting.enable = true;
# Enable NVIDIA Open GPU Kernel Modules (Turing architecture or newer —
# this RTX 4050 is Ada Lovelace, well within support)
open = true;
# Enable the NVIDIA settings menu
nvidiaSettings = true;
# Use the stable driver package matching current kernel
package = config.boot.kernelPackages.nvidiaPackages.stable;
# Fixes suspend/resume hangs that are common with NVIDIA on laptops.
powerManagement.enable = true;
# PRIME render offload: the AMD iGPU drives the display at all times
# (much better battery life than keeping the dGPU powered on), and the
# NVIDIA GPU is only spun up on demand for a specific process — run
# anything with `nvidia-offload <command>` (generated by
# enableOffloadCmd) to route it through the RTX 4050, e.g. games or
# Blender's Cycles renderer.
prime = {
offload = {
enable = true;
enableOffloadCmd = true;
};
amdgpuBusId = "PCI:53:0:0";
nvidiaBusId = "PCI:1:0:0";
};
};
# ASUS laptop control: keyboard backlight/fan curves/battery charge limit
# (asusctl) and dGPU power-state switching between Integrated/Hybrid modes
# (supergfxctl) — the two standard asus-linux.org daemons for ROG/TUF
# laptops, both packaged directly in nixpkgs.
services.asusd.enable = true;
services.supergfxd.enable = true;
}

7
modules/fastfetch.nix Normal file
View file

@ -0,0 +1,7 @@
{ config, pkgs, ... }:
{
# System-wide config; fastfetch searches /etc/xdg/fastfetch/ after
# ~/.config/fastfetch/, so a user config there would still win.
environment.etc."xdg/fastfetch/config.jsonc".source = ../configs/fastfetch/config.jsonc;
}

36
modules/firefox.nix Normal file
View file

@ -0,0 +1,36 @@
{ config, pkgs, ... }:
let
# Firefox's own font setup: every system font except the Microsoft core
# fonts. Sites measure which fonts are installed to fingerprint you, and
# Comic Sans, Impact, Georgia, Verdana... made that list 1 in 9,000.
# Only Firefox is affected: other apps still have corefonts. In Firefox,
# Arial, Times New Roman and Courier New render as Liberation (same
# letter widths), the rest fall back to Noto.
firefoxFonts = pkgs.writeText "firefox-fonts.conf" ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
<include ignore_missing="no">/etc/fonts/fonts.conf</include>
<selectfont>
<rejectfont>
<glob>${pkgs.corefonts}/*</glob>
</rejectfont>
</selectfont>
</fontconfig>
'';
in
{
programs.firefox = {
enable = true;
# The wrapper sets FONTCONFIG_FILE when Firefox starts. (overrideAttrs
# keeps the package overridable, so the autoConfig below still applies.)
package = pkgs.firefox.overrideAttrs (old: {
makeWrapperArgs = old.makeWrapperArgs ++ [ "--set" "FONTCONFIG_FILE" "${firefoxFonts}" ];
});
# Not locked: values are reapplied on every Firefox start, but can be
# changed in the UI for the current session. (Read as text: the module
# doesn't copy autoConfigFiles paths into the store.)
autoConfig = builtins.readFile ../configs/firefox/prefs.js;
};
}

76
modules/hardware.nix Normal file
View file

@ -0,0 +1,76 @@
{ config, lib, pkgs, ... }:
{
hardware.graphics = {
enable = true;
enable32Bit = true;
};
# Hybrid graphics on the ASUS TUF Gaming A15 (FA507NU): AMD Radeon 680M
# iGPU drives the internal panel, NVIDIA RTX 4050 Max-Q is offload-only.
# Run something on the dGPU with `nvidia-offload <command>`.
# Bus IDs from `lspci` on this machine: 01:00.0 (NVIDIA) -> PCI:1:0:0,
# 35:00.0 (AMD) -> PCI:53:0:0.
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia = {
modesetting.enable = true;
open = true;
nvidiaSettings = true;
package = config.boot.kernelPackages.nvidiaPackages.stable;
# Fixes suspend/resume hangs common with NVIDIA on laptops.
powerManagement.enable = true;
prime = {
offload = {
enable = true;
enableOffloadCmd = true;
};
amdgpuBusId = "PCI:53:0:0";
nvidiaBusId = "PCI:1:0:0";
};
};
# No LIBVA/NVD env vars here (unlike the PC): video decoding runs on the
# AMD iGPU, which libva picks automatically (radeonsi).
# asusctl (fan curves, keyboard backlight, battery charge limit) and
# supergfxctl (dGPU power-state switching), from asus-linux.org.
services.asusd.enable = true;
services.supergfxd.enable = true;
hardware.opentabletdriver.enable = true;
hardware.uinput.enable = true;
boot.kernelModules = [ "uinput" ];
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
settings = {
General = {
Experimental = true; # Battery level of connected devices
FastConnectable = true; # Faster reconnects, more power draw
};
Policy = {
AutoEnable = true;
};
};
};
# Plasma ships its own Bluetooth UI (Bluedevil); blueman just duplicated it.
boot.extraModprobeConfig = ''
# DualSense/PS4 pads pair over Bluetooth then drop instantly; broken
# ERTM in many adapters. Disabling it is the standard fix.
options bluetooth disable_ertm=1
'';
# Blog V4 needs the rtlsdrblog fork of librtlsdr, which is what
# pkgs.rtl-sdr already is here. Also blacklists the DVB-T drivers.
hardware.rtl-sdr.enable = true;
# For ddcutil on an external monitor; the internal panel uses the kernel
# backlight instead (brightness-ctl picks whichever applies).
hardware.i2c.enable = true;
services.printing.enable = true;
}

19
modules/locale.nix Normal file
View file

@ -0,0 +1,19 @@
{ config, pkgs, ... }:
{
time.timeZone = "Europe/Warsaw";
i18n.defaultLocale = "pl_PL.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "pl_PL.UTF-8";
LC_IDENTIFICATION = "pl_PL.UTF-8";
LC_MEASUREMENT = "pl_PL.UTF-8";
LC_MONETARY = "pl_PL.UTF-8";
LC_NAME = "pl_PL.UTF-8";
LC_NUMERIC = "pl_PL.UTF-8";
LC_PAPER = "pl_PL.UTF-8";
LC_TELEPHONE = "pl_PL.UTF-8";
LC_TIME = "pl_PL.UTF-8";
};
console.keyMap = "pl2";
}

38
modules/networking.nix Normal file
View file

@ -0,0 +1,38 @@
{ config, pkgs, ... }:
{
networking.hostName = "nexo-laptop";
networking.networkmanager.enable = true;
networking.firewall = {
enable = true;
allowPing = true;
allowedTCPPortRanges = [ { from = 1714; to = 1764; } ];
allowedUDPPortRanges = [ { from = 1714; to = 1764; } ];
allowedTCPPorts = [ 80 443 ];
};
# DNS-over-TLS via systemd-resolved; NetworkManager defers to it rather
# than writing its own /etc/resolv.conf.
networking.nameservers = [ "1.1.1.1#cloudflare-dns.com" "9.9.9.9#dns.quad9.net" ];
services.resolved = {
enable = true;
settings.Resolve = {
DNSSEC = "allow-downgrade";
DNSOverTLS = "true";
};
};
networking.networkmanager.dns = "systemd-resolved";
# Ethernet stays "stable" (pseudonymous but consistent) so static DHCP
# reservations on the router keep working; Wi-Fi is fully random.
networking.networkmanager.wifi.macAddress = "random";
networking.networkmanager.wifi.scanRandMacAddress = true;
networking.networkmanager.ethernet.macAddress = "stable";
# Disable NetworkManager's periodic captive-portal probe.
networking.networkmanager.settings.connectivity = {
uri = "";
interval = 0;
};
}

14
modules/nix-settings.nix Normal file
View file

@ -0,0 +1,14 @@
{ config, pkgs, ... }:
{
nixpkgs.config.allowUnfree = true;
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.auto-optimise-store = true;
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
}

38
modules/remote.nix Normal file
View file

@ -0,0 +1,38 @@
{ config, lib, pkgs, ... }:
# My machines working together at home: SSH (keys only) and ZeroVRAM's zvm_node (port 8080),
# both reachable from the home network only — not from other networks the laptop joins.
let
homeLan = "192.168.1.0/24";
homePorts = [ 22 8080 ]; # SSH, zvm_node
rule = op: port: "iptables ${op} nixos-fw -p tcp -s ${homeLan} --dport ${toString port} -j nixos-fw-accept";
in
{
# Fixed names for the machines (their addresses are reserved in the router). The router's own
# *.lan names don't resolve here: DNS goes over TLS to public resolvers (networking.nix).
networking.hosts = {
"192.168.1.225" = [ "nexo-pc" ];
"192.168.1.197" = [ "nexo-laptop" ];
};
services.openssh = {
enable = true;
openFirewall = false; # opened below for the home network only
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
AllowUsers = [ "nexoniarz" ];
};
};
# Keys allowed to log in here: the PC
users.users."nexoniarz".openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAPXDmX7gYH0A2zez4f1F63kjAI8t7iyte+gXmyI4wtz nexoniarz@nexo-pc"
];
# Inserted at the top of the firewall chain (rules appended at the end would come after its
# final reject); removed again when the firewall stops or reloads.
networking.firewall.extraCommands = lib.concatMapStringsSep "\n" (rule "-I") homePorts;
networking.firewall.extraStopCommands = lib.concatMapStringsSep "\n" (p: "${rule "-D" p} || true") homePorts;
}

View file

@ -1,16 +1,45 @@
{ config, pkgs, ... }:
{ config, pkgs, lib, ... }:
let
# Wrap external shell scripts into system executables
vaultToggle = pkgs.writeShellScriptBin "vault-toggle" (builtins.readFile ./scripts/vault-toggle.sh);
stripMetadata = pkgs.writeShellScriptBin "strip-metadata" (builtins.readFile ./scripts/strip-metadata.sh);
brightnessCtl = pkgs.writeShellScriptBin "brightness-ctl" (builtins.readFile ./scripts/brightness-ctl.sh);
hotspotStart = pkgs.writeShellScriptBin "hotspot-start" (builtins.readFile ./scripts/hotspot-start.sh);
systemTelemetry = pkgs.writeShellScriptBin "system-telemetry" (builtins.readFile ./scripts/system-telemetry.sh);
weatherFetch = pkgs.writeShellScriptBin "weather-fetch" (builtins.readFile ./scripts/weather-fetch.sh);
nexopass = pkgs.writeShellApplication {
name = "nexopass";
runtimeInputs = with pkgs; [ libargon2 gnupg wl-clipboard keyutils coreutils gnused ];
runtimeEnv.NEXOPASS_WORDLIST = "${./scripts/eff_large_wordlist.txt}";
text = builtins.readFile ./scripts/nexopass.sh;
};
# NexoPass window (github.com/Nexoniarz/NexoPass). Shares accounts, site
# lists and the app password with the nexopass command above.
nexopassGuiVersion = "1.3.1";
nexopassGuiJar = pkgs.fetchurl {
url = "https://github.com/Nexoniarz/NexoPass/releases/download/v${nexopassGuiVersion}/NexoPass-linux-x64-${nexopassGuiVersion}.jar";
hash = "sha256-WeUixuz+aLPsMDj+a0Gs09gfikMYYCf8uuZIN89CqVo=";
};
nexopassGuiLibs = with pkgs; [ libGL libx11 libxext libxrender libxtst libxi libxrandr libxcursor fontconfig freetype ];
nexopassGuiDesktop = pkgs.makeDesktopItem {
name = "nexopass";
desktopName = "NexoPass";
comment = "Passwords derived from a master";
exec = "nexopass-gui";
icon = "nexopass";
categories = [ "Utility" "Security" ];
};
nexopassGui = pkgs.runCommand "nexopass-gui-${nexopassGuiVersion}" { nativeBuildInputs = [ pkgs.makeWrapper ]; } ''
makeWrapper ${pkgs.jdk17}/bin/java $out/bin/nexopass-gui \
--add-flags "-Xmx1g -jar ${nexopassGuiJar}" \
--prefix LD_LIBRARY_PATH : /run/opengl-driver/lib:${lib.makeLibraryPath nexopassGuiLibs}
install -Dm644 ${./scripts/nexopass.png} $out/share/icons/hicolor/512x512/apps/nexopass.png
install -Dm644 ${nexopassGuiDesktop}/share/applications/nexopass.desktop $out/share/applications/nexopass.desktop
'';
in
{
# Install CLI dependencies required by the scripts
environment.systemPackages = with pkgs; [
gocryptfs
exiftool
@ -21,5 +50,7 @@ in
hotspotStart
systemTelemetry
weatherFetch
nexopass
nexopassGui
];
}

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

1390
modules/scripts/nexopass.sh Executable file

File diff suppressed because it is too large Load diff

38
modules/security.nix Normal file
View file

@ -0,0 +1,38 @@
{ config, pkgs, ... }:
{
security.polkit.enable = true;
security.sudo.extraConfig = ''
Defaults pwfeedback
'';
programs.firejail.enable = true;
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
pinentryPackage = pkgs.pinentry-rofi;
};
boot.kernel.sysctl = {
"kernel.kptr_restrict" = 2;
"kernel.dmesg_restrict" = 1;
"net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.all.accept_redirects" = false;
"net.ipv4.conf.default.accept_redirects" = false;
"net.ipv6.conf.all.accept_redirects" = false;
"net.ipv6.conf.default.accept_redirects" = false;
"net.ipv4.conf.all.send_redirects" = false;
"net.ipv4.conf.default.send_redirects" = false;
# Only bites ad-hoc `gdb -p <pid>` on a non-child process.
"kernel.yama.ptrace_scope" = 1;
"net.ipv4.tcp_timestamps" = 0;
};
systemd.coredump.enable = false;
security.protectKernelImage = true;
services.geoclue2.enable = false;
}

View file

@ -1,204 +0,0 @@
{ config, lib, pkgs, ... }:
{
# Bootloader & Kernel
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.configurationLimit = 5;
boot.kernelPackages = pkgs.linuxPackages;
boot.supportedFilesystems = [ "fuse" ];
# Networking
networking.hostName = "nixos";
networking.networkmanager.enable = true;
# Firewall Configuration
networking.firewall = {
enable = true;
# Allow local ping diagnostic queries
allowPing = true;
allowedTCPPortRanges = [ { from = 1714; to = 1764; } ];
allowedUDPPortRanges = [ { from = 1714; to = 1764; } ];
allowedTCPPorts = [ 80 443 ];
# allowedUDPPorts = [ ];
};
# Time zone and Internationalization
time.timeZone = "Europe/Warsaw";
i18n.defaultLocale = "pl_PL.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "pl_PL.UTF-8";
LC_IDENTIFICATION = "pl_PL.UTF-8";
LC_MEASUREMENT = "pl_PL.UTF-8";
LC_MONETARY = "pl_PL.UTF-8";
LC_NAME = "pl_PL.UTF-8";
LC_NUMERIC = "pl_PL.UTF-8";
LC_PAPER = "pl_PL.UTF-8";
LC_TELEPHONE = "pl_PL.UTF-8";
LC_TIME = "pl_PL.UTF-8";
};
nix.settings.auto-optimise-store = true;
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
# Console keymap
console.keyMap = "pl2";
# Sound and Audio (Pipewire)
security.rtkit.enable = true;
services.pulseaudio.enable = false;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
settings = {
General = {
# Shows battery charge of connected devices on supported
# Bluetooth adapters. Defaults to 'false'.
Experimental = true;
# When enabled other devices can connect faster to us, however
# the tradeoff is increased power consumption. Defaults to
# 'false'.
FastConnectable = true;
};
Policy = {
# Enable all controllers when they are found. This includes
# adapters present on start as well as adapters that are plugged
# in later on. Defaults to 'true'.
AutoEnable = true;
};
};
};
services.blueman.enable = true;
#Firejail
programs.firejail = {
enable = true;
};
#FUSE shit
programs.fuse.userAllowOther = true;
# Enable GnuPG Agent with GUI pinentry support
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
pinentryPackage = pkgs.pinentry-gnome3; # Matches Pantheon's GTK/gnome-keyring stack
};
security.sudo.extraConfig = ''
Defaults pwfeedback
'';
# Printing services
services.printing.enable = true;
nixpkgs.config.allowUnfree = true;
fonts.packages = with pkgs; [
corefonts
dejavu_fonts
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
nerd-fonts.fira-code
nerd-fonts.jetbrains-mono
nerd-fonts.hack
inter
liberation_ttf
roboto
];
# --- Loader shim for running non-Nix-packaged binaries (e.g. the official
# Tor Browser bundle) that expect a standard FHS dynamic linker/libraries. ---
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
glib gtk3 gdk-pixbuf pango cairo atk
dbus dbus-glib fontconfig freetype
libx11 libxext libxrender libxtst
libxi libxcomposite libxdamage libxfixes
libxrandr libxcursor libxcb libxkbcommon
alsa-lib mesa zlib stdenv.cc.cc
];
environment.systemPackages = [ pkgs.file ];
# --- Hardening: swap, kernel sysctls, DNS, MAC randomization ---
# Swap: replace disk swap with compressed in-RAM swap. Nothing sensitive
# (decrypted vault contents, browser memory, GPG session data) ever gets
# written to disk in plaintext via swap. Also faster than disk swap under
# memory pressure.
zramSwap.enable = true;
swapDevices = lib.mkForce [ ];
# systemd's gpt-auto-generator independently re-discovers and activates any
# GPT partition tagged as Linux swap, regardless of the swapDevices list
# above — this disables that auto-discovery so the old disk swap partition
# actually stays off. Doesn't affect /, /home, /nix, /boot: those are
# already explicitly declared in hardware-configuration.nix, not relying on
# gpt-auto. Takes effect on next reboot.
boot.kernelParams = [ "systemd.gpt_auto=0" ];
# Kernel/system hardening sysctls
boot.kernel.sysctl = {
# Hide kernel pointers from unprivileged users (blocks a common
# local info-leak used in exploit chains).
"kernel.kptr_restrict" = 2;
# Restrict dmesg access to root.
"kernel.dmesg_restrict" = 1;
# Reverse-path filtering: drop packets with spoofed source addresses.
"net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.default.rp_filter" = 1;
# Don't accept/send ICMP redirects (blocks a classic local MITM trick).
"net.ipv4.conf.all.accept_redirects" = false;
"net.ipv4.conf.default.accept_redirects" = false;
"net.ipv6.conf.all.accept_redirects" = false;
"net.ipv6.conf.default.accept_redirects" = false;
"net.ipv4.conf.all.send_redirects" = false;
"net.ipv4.conf.default.send_redirects" = false;
};
# Crash dumps can contain decrypted memory contents, passwords, keys —
# never write them to disk.
systemd.coredump.enable = false;
# Blocks kexec-based kernel image tampering.
security.protectKernelImage = true;
# DNS-over-TLS system-wide (Tor Browser already routes its own DNS
# through Tor, so this only affects everything else). Cloudflare + Quad9
# both support DoT; "allow-downgrade" avoids hard failures on domains
# with broken DNSSEC deployment.
networking.nameservers = [ "1.1.1.1#cloudflare-dns.com" "9.9.9.9#dns.quad9.net" ];
services.resolved = {
enable = true;
settings.Resolve = {
DNSSEC = "allow-downgrade";
DNSOverTLS = "true";
};
};
networking.networkmanager.dns = "systemd-resolved";
# MAC address randomization.
# WiFi: fully random per connection (you're on ethernet now, but this
# protects you if you ever use WiFi).
# Ethernet: "stable" — a consistent pseudonymous MAC per connection
# profile rather than your real hardware MAC, so it won't break any
# static DHCP reservation/MAC filtering on your OpenWRT router, while
# still not exposing your real hardware identity.
networking.networkmanager.wifi.macAddress = "random";
networking.networkmanager.wifi.scanRandMacAddress = true;
networking.networkmanager.ethernet.macAddress = "stable";
}

View file

@ -1,27 +1,26 @@
{ config, pkgs, ... }:
{
# Primary user account configuration (Access and settings only)
users.users."nexoniarz" = {
isNormalUser = true;
description = "Nexoniarz";
extraGroups = [ "networkmanager" "wheel" "fuse" "i2c" "video" ];
extraGroups = [ "networkmanager" "wheel" "fuse" "i2c" "video" "plugdev" ];
shell = pkgs.zsh;
};
# Default shell (ZSH)
programs.zsh.enable = true;
# Web browser configuration
programs.firefox.enable = true;
# Enable Steam with optimized system configurations
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
};
# Enable Flatpak support
services.flatpak.enable = true;
# Flatpak's exported .desktop files aren't on XDG_DATA_DIRS by default,
# so Bottles would otherwise not show up in the launcher.
systemd.tmpfiles.rules = [
"L+ /var/lib/flatpak/exports/share/applications - - - - /var/lib/flatpak/app/com.usebottles.bottles/current/active/export/share/applications"
];
}