diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f31450 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.tokens diff --git a/configuration.nix b/configuration.nix index 3f1a584..5ab2082 100644 --- a/configuration.nix +++ b/configuration.nix @@ -7,11 +7,15 @@ { imports = [ # Include the results of the hardware scan. - ./hardware-configuration.nix + ./system-modules/hardware-configuration.nix + ./system-modules/users.nix + ./system-modules/sound.nix + ./system-modules/ollama.nix + + ./system-modules/hsmw.nix + ]; - # Use the systemd-boot EFI boot loader. - # boot.loader.systemd-boot.enable = false; boot.loader.efi.canTouchEfiVariables = true; boot.loader.grub = { enable = true; @@ -22,44 +26,25 @@ }; - networking.hostName = "NxXPS"; # Define your hostname. + networking.hostName = "NxXPS"; networking.networkmanager = { enable = true; - # enableStrongSwan = true; }; - environment.etc = { - # easyroam HSMW - "ssl/certs/easyroam_client_cert.pem".source = ./secrets/easyroam-hsmw/easyroam_client_cert.pem; - "ssl/certs/easyroam_root_ca.pem".source = ./secrets/easyroam-hsmw/easyroam_root_ca.pem; - "ssl/certs/easyroam_client_key.pem".source = ./secrets/easyroam-hsmw/easyroam_client_key.pem; - "NetworkManager/system-connections/eduroam.nmconnection" = { - text = secrets.easyroamHSMW.nmconfig; - mode = "0600"; - }; - }; + + # Set your time zone. time.timeZone = "Europe/Berlin"; - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; - console = { - font = "Lat2-Terminus16"; - keyMap = "de"; -# useXkbConfig = true; # use xkb.options in tty. - }; + console.font = "Lat2-Terminus16"; + console.keyMap = "de"; # Enable the X11 windowing system. services.xserver.enable = true; - - - # Configure keymap in X11 services.xserver.xkb.layout = "de"; services.xserver.xkb.options = "eurosign:e,caps:escape"; @@ -67,59 +52,21 @@ # Enable CUPS to print documents. services.printing.enable = true; - # Enable sound. - #sound.enable = true; - #hardware.pulseaudio.enable = true; - # rtkit is optional but recommended security.rtkit.enable = true; - - - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - # If you want to use JACK applications, uncomment this - jack.enable = true; - }; - # Enable touchpad support (enabled default in most desktopManager). services.xserver.libinput.enable = true; hardware.uinput.enable = true; - users.defaultUserShell = pkgs.bash; # if interactive, itll switch to fish - programs.bash = { - interactiveShellInit = '' - if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]] - then - shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION="" - exec ${pkgs.fish}/bin/fish $LOGIN_OPTION - fi - ''; - }; + # log into this machine + services.openssh.enable = false; - users.users.nx2 = { - isNormalUser = true; - extraGroups = [ "networkmanager" "wheel" "audio" "video" "docker" "libvirtd" "uinput" ]; - useDefaultShell = true; - packages = with pkgs; []; # all in home.nix - }; - - nixpkgs.config = { - allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) allowed.unfree-packages; - permittedInsecurePackages = [ - "electron-25.9.0" - ]; - }; # List packages installed in system profile. To search, run: # $ nix search wget environment.systemPackages = with pkgs; [ ntfs3g - fish - starship git git-crypt wget @@ -127,32 +74,14 @@ zip unzip p7zip - killall + unar nano micro - yazi - bat - du-dust htop - eza - zoxide - neofetch direnv openssl - openvpn - ollama # maybe ]; - environment.sessionVariables = rec { - XDG_CACHE_HOME = "$HOME/.cache"; - GTK_THEME = "Adwaita-Dark"; - }; - environment.variables = rec { - XDG_CACHE_HOME = "$HOME/.cache"; - GTK_THEME = "Adwaita-Dark"; - }; - - fonts.packages = with pkgs; [ noto-fonts noto-fonts-cjk @@ -162,95 +91,23 @@ ]; - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. programs.gnupg.agent = { enable = true; enableSSHSupport = true; }; - programs.fish = { - enable = true; - }; - programs.hyprland = { + + + programs.hyprland = { # config is done with home-manager enable = true; xwayland.enable = true; }; - - ### OLLAMA - systemd.services.ollama = { - description = "Ollama Service"; - after = [ "network-online.target" "ollama-doesnt-respect-xdg-data-home.service" ]; - serviceConfig = { - Type = "simple"; - # Environment = "\"XDG_DATA_HOME=/run/current-system/sw/share\""; - ExecStart = "${pkgs.ollama}/bin/ollama serve"; - User = "ollama"; - Group = "ollama"; - Restart = "always"; - RestartSec = "3"; - }; - wantedBy = [ "default.target" ]; - }; - - users.users.ollama = { - isSystemUser = true; - home = "/usr/share/ollama"; - shell = "/bin/false"; - group = "ollama"; - }; - users.groups.ollama = {}; - - systemd.services.ollama-doesnt-respect-xdg-data-home = { - wantedBy = ["multi-user.target"]; - script = '' - mkdir -p /usr/share/ollama/.ollama - chown ollama:ollama -R /usr/share/ollama - ''; - }; - - ### END OLLAMA - - - - - - - - # List services that you want to enable: - - # Enable the OpenSSH daemon. - services.openssh.enable = true; - - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; - - # This option defines the first version of NixOS you have installed on this particular machine, - # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. - # - # Most users should NEVER change this value after the initial install, for any reason, - # even if you've upgraded your system to a new NixOS release. - # - # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, - # so changing it will NOT upgrade your system. - # - # This value being lower than the current NixOS release does NOT mean your system is - # out of date, out of support, or vulnerable. - # - # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, - # and migrated your data accordingly. - # - # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . - system.stateVersion = "23.11"; # Did you read the comment? - + system.stateVersion = "23.11"; nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + + programs.bash.shellInit = '' + source $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh + ''; } \ No newline at end of file diff --git a/flake.lock b/flake.lock index fdc5cc3..3c8d0f6 100644 --- a/flake.lock +++ b/flake.lock @@ -23,11 +23,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1709569716, - "narHash": "sha256-iOR44RU4jQ+YPGrn+uQeYAp7Xo7Z/+gT+wXJoGxxLTY=", + "lastModified": 1710162809, + "narHash": "sha256-i2R2bcnQp+85de67yjgZVvJhd6rRnJbSYNpGmB6Leb8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "617579a787259b9a6419492eaac670a5f7663917", + "rev": "ddcd7598b2184008c97e6c9c6a21c5f37590b8d2", "type": "github" }, "original": { diff --git a/home-modules/gestures.nix b/home-modules/gestures.nix new file mode 100644 index 0000000..57e3339 --- /dev/null +++ b/home-modules/gestures.nix @@ -0,0 +1,17 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.libinput-gestures + pkgs.ydotool + ]; + + home.file.".config/libinput/gestures".text = '' + # Swipe threshold (0-100) + swipe_threshold 0 + + # Gestures + gesture swipe left 3 echo key k:276 | dotool + gesture swipe right 3 echo key k:275 | dotool +''; +} \ No newline at end of file diff --git a/home-modules/git.nix b/home-modules/git.nix new file mode 100644 index 0000000..e69de29 diff --git a/home-modules/hyprland/hyprland-autoname-workspaces.nix b/home-modules/hyprland/hyprland-autoname-workspaces.nix new file mode 100644 index 0000000..a597821 --- /dev/null +++ b/home-modules/hyprland/hyprland-autoname-workspaces.nix @@ -0,0 +1,109 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.hyprland-autoname-workspaces + ]; + + home.file.".config/hyprland-autoname-workspaces/config.toml".text = '' + version = "1.1.13" + + [class] + Signal = "󱅵" + DEFAULT = "{class}" + libreoffice-writer = "" + pavucontrol = "󰕾" + "epicgameslauncher.exe" = "󰯷" + "riotclientux.exe" = "󰰌" + "[Cc]ode" = "󰨞" + VirtualBox = "" + KiCad = "" + Gimp = "" + code-oss = "󰨞" + VSCodium = "󰨞" + Alacritty = "" + kitty = "" + vesktop = "󰙯" + "cyberpunk2077.exe" = "󰾲" + "Tor Browser" = "󰾔" + "[Tt]hunderbird" = "" + Element = "󰘨" + blueman-manager = "󰂯" + obsidian = "󰠮" + libreoffice-calc = "" + zoom = "󰬡" + mpv = "" + chatterino = "" + "com.obsproject.Studio" = "" + "leagueclientux.exe" = "󰰌" + "[sS]potify" = "" + "org.remmina.Remmina" = "󰢹" + steam = "󰓓" + "galaxyclient.exe" = "󰮡" + "[Ff]irefox" = "󰈹" + pcbnew = "" + ".*.exe" = "" + Chromium = "" + virt-manager = "" + Bitwarden = "" + "[tT]hunar" = "" + zathura = "󰈦" + discord = "󰙯" + "VirtualBox Manager" = "" + "org.inkscape.Inkscape" = "󰕙" + "VirtualBox Machine" = "" + lutris = "󰊗" + "[gG]imp-.*" = "" + + [class_active] + "(?i)ExampleOneTerm" = "icon" + + [initial_class] + + [initial_class_active] + + [workspaces_name] + 10 = "ten" + 4 = "four" + 8 = "eight" + 9 = "nine" + 6 = "six" + 1 = "one" + 3 = "three" + 2 = "two" + 0 = "zero" + 7 = "seven" + 5 = "five" + + [title_in_class] + [title_in_class_active] + [title_in_initial_class] + [title_in_initial_class_active] + [initial_title_in_class] + [initial_title_in_class_active] + [initial_title_in_initial_class] + [initial_title_in_initial_class_active] + + [exclude] + "(?i)fcitx" = ".*" + aProgram = "^$" + "ueberzug.*" = "" + "" = "^$" + "[Ss]team" = "^(Friends List.*)?$" + "explorer.exe" = ".*" + "(?i)TestApp" = "" + + [format] + dedup = false + dedup_inactive_fullscreen = false + delim = " " + workspace = "{id}: {clients}" + workspace_empty = "{id}" + client = "{icon}" + client_fullscreen = "{icon}" + client_active = "{icon}" + client_dup = "{icon}{counter_sup}" + client_dup_active = "*{icon}*{delim}{icon}{counter_unfocused_sup}" + client_dup_fullscreen = "[{icon}]{delim}{icon}{counter_unfocused_sup}" + ''; +} \ No newline at end of file diff --git a/home-modules/hyprland/hyprland.nix b/home-modules/hyprland/hyprland.nix new file mode 100644 index 0000000..43d4835 --- /dev/null +++ b/home-modules/hyprland/hyprland.nix @@ -0,0 +1,10 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + # hyprland itself is a system package + pkgs.hyprland-protocols + ]; + + +} \ No newline at end of file diff --git a/home-modules/mutt/mutt_oauth2.py b/home-modules/mutt/mutt_oauth2.py new file mode 100755 index 0000000..1d07394 --- /dev/null +++ b/home-modules/mutt/mutt_oauth2.py @@ -0,0 +1,421 @@ +#!/usr/bin/env python3 +# +# Mutt OAuth2 token management script, version 2020-08-07 +# Written against python 3.7.3, not tried with earlier python versions. +# +# Copyright (C) 2020 Alexander Perlis +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. +'''Mutt OAuth2 token management''' + +import sys +import json +import argparse +import urllib.parse +import urllib.request +import imaplib +import poplib +import smtplib +import base64 +import secrets +import hashlib +import time +from datetime import timedelta, datetime +from pathlib import Path +import socket +import http.server +import subprocess +import readline + +# The token file must be encrypted because it contains multi-use bearer tokens +# whose usage does not require additional verification. Specify whichever +# encryption and decryption pipes you prefer. They should read from standard +# input and write to standard output. The example values here invoke GPG, +# although won't work until an appropriate identity appears in the first line. +ENCRYPTION_PIPE = ['gpg', '--encrypt', '--recipient', 'Lennart J. Kurzweg (mutt-email)'] +DECRYPTION_PIPE = ['gpg', '--decrypt'] + +registrations = { + 'lkgoogle': { + 'authorize_endpoint': 'https://accounts.google.com/o/oauth2/auth', + 'devicecode_endpoint': 'https://oauth2.googleapis.com/device/code', + 'token_endpoint': 'https://accounts.google.com/o/oauth2/token', + 'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob', + 'imap_endpoint': 'imap.gmail.com', + 'pop_endpoint': 'pop.gmail.com', + 'smtp_endpoint': 'smtp.gmail.com', + 'sasl_method': 'OAUTHBEARER', + 'scope': 'https://mail.google.com/', + 'client_id': '860100429226-04or541aqhj06u09i4nq07mbq9q3l5c9.apps.googleusercontent.com', + 'client_secret': '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', # this is just a pointer to "my develloper app" not nothing secret + }, + 'microsoft': { + 'authorize_endpoint': 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', + 'devicecode_endpoint': 'https://login.microsoftonline.com/common/oauth2/v2.0/devicecode', + 'token_endpoint': 'https://login.microsoftonline.com/common/oauth2/v2.0/token', + 'redirect_uri': 'https://login.microsoftonline.com/common/oauth2/nativeclient', + 'tenant': 'common', + 'imap_endpoint': 'outlook.office365.com', + 'pop_endpoint': 'outlook.office365.com', + 'smtp_endpoint': 'smtp.office365.com', + 'sasl_method': 'XOAUTH2', + 'scope': ('offline_access https://outlook.office.com/IMAP.AccessAsUser.All ' + 'https://outlook.office.com/POP.AccessAsUser.All ' + 'https://outlook.office.com/SMTP.Send'), + 'client_id': '', + 'client_secret': '', + }, +} + +ap = argparse.ArgumentParser(epilog=''' +This script obtains and prints a valid OAuth2 access token. State is maintained in an +encrypted TOKENFILE. Run with "--verbose --authorize" to get started or whenever all +tokens have expired, optionally with "--authflow" to override the default authorization +flow. To truly start over from scratch, first delete TOKENFILE. Use "--verbose --test" +to test the IMAP/POP/SMTP endpoints. +''') +ap.add_argument('-v', '--verbose', action='store_true', help='increase verbosity') +ap.add_argument('-d', '--debug', action='store_true', help='enable debug output') +ap.add_argument('tokenfile', help='persistent token storage') +ap.add_argument('-a', '--authorize', action='store_true', help='manually authorize new tokens') +ap.add_argument('--authflow', help='authcode | localhostauthcode | devicecode') +ap.add_argument('-t', '--test', action='store_true', help='test IMAP/POP/SMTP endpoints') +args = ap.parse_args() + +token = {} +path = Path(args.tokenfile) +if path.exists(): + if 0o777 & path.stat().st_mode != 0o600: + sys.exit('Token file has unsafe mode. Suggest deleting and starting over.') + try: + sub = subprocess.run(DECRYPTION_PIPE, check=True, input=path.read_bytes(), + capture_output=True) + token = json.loads(sub.stdout) + except subprocess.CalledProcessError: + sys.exit('Difficulty decrypting token file. Is your decryption agent primed for ' + 'non-interactive usage, or an appropriate environment variable such as ' + 'GPG_TTY set to allow interactive agent usage from inside a pipe?') + + +def writetokenfile(): + '''Writes global token dictionary into token file.''' + if not path.exists(): + path.touch(mode=0o600) + if 0o777 & path.stat().st_mode != 0o600: + sys.exit('Token file has unsafe mode. Suggest deleting and starting over.') + sub2 = subprocess.run(ENCRYPTION_PIPE, check=True, input=json.dumps(token).encode(), + capture_output=True) + path.write_bytes(sub2.stdout) + + +if args.debug: + print('Obtained from token file:', json.dumps(token)) +if not token: + if not args.authorize: + sys.exit('You must run script with "--authorize" at least once.') + print('Available app and endpoint registrations:', *registrations) + token['registration'] = input('OAuth2 registration: ') + token['authflow'] = input('Preferred OAuth2 flow ("authcode" or "localhostauthcode" ' + 'or "devicecode"): ') + token['email'] = input('Account e-mail address: ') + token['access_token'] = '' + token['access_token_expiration'] = '' + token['refresh_token'] = '' + writetokenfile() + +if token['registration'] not in registrations: + sys.exit(f'ERROR: Unknown registration "{token["registration"]}". Delete token file ' + f'and start over.') +registration = registrations[token['registration']] + +authflow = token['authflow'] +if args.authflow: + authflow = args.authflow + +baseparams = {'client_id': registration['client_id']} +# Microsoft uses 'tenant' but Google does not +if 'tenant' in registration: + baseparams['tenant'] = registration['tenant'] + + +def access_token_valid(): + '''Returns True when stored access token exists and is still valid at this time.''' + token_exp = token['access_token_expiration'] + return token_exp and datetime.now() < datetime.fromisoformat(token_exp) + + +def update_tokens(r): + '''Takes a response dictionary, extracts tokens out of it, and updates token file.''' + token['access_token'] = r['access_token'] + token['access_token_expiration'] = (datetime.now() + + timedelta(seconds=int(r['expires_in']))).isoformat() + if 'refresh_token' in r: + token['refresh_token'] = r['refresh_token'] + writetokenfile() + if args.verbose: + print(f'NOTICE: Obtained new access token, expires {token["access_token_expiration"]}.') + + +if args.authorize: + p = baseparams.copy() + p['scope'] = registration['scope'] + + if authflow in ('authcode', 'localhostauthcode'): + verifier = secrets.token_urlsafe(90) + challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest())[:-1] + redirect_uri = registration['redirect_uri'] + listen_port = 0 + if authflow == 'localhostauthcode': + # Find an available port to listen on + s = socket.socket() + s.bind(('127.0.0.1', 0)) + listen_port = s.getsockname()[1] + s.close() + redirect_uri = 'http://localhost:'+str(listen_port)+'/' + # Probably should edit the port number into the actual redirect URL. + + p.update({'login_hint': token['email'], + 'response_type': 'code', + 'redirect_uri': redirect_uri, + 'code_challenge': challenge, + 'code_challenge_method': 'S256'}) + print(registration["authorize_endpoint"] + '?' + + urllib.parse.urlencode(p, quote_via=urllib.parse.quote)) + + authcode = '' + if authflow == 'authcode': + authcode = input('Visit displayed URL to retrieve authorization code. Enter ' + 'code from server (might be in browser address bar): ') + else: + print('Visit displayed URL to authorize this application. Waiting...', + end='', flush=True) + + class MyHandler(http.server.BaseHTTPRequestHandler): + '''Handles the browser query resulting from redirect to redirect_uri.''' + + # pylint: disable=C0103 + def do_HEAD(self): + '''Response to a HEAD requests.''' + self.send_response(200) + self.send_header('Content-type', 'text/html') + self.end_headers() + + def do_GET(self): + '''For GET request, extract code parameter from URL.''' + # pylint: disable=W0603 + global authcode + querystring = urllib.parse.urlparse(self.path).query + querydict = urllib.parse.parse_qs(querystring) + if 'code' in querydict: + authcode = querydict['code'][0] + self.do_HEAD() + self.wfile.write(b'Authorizaton result') + self.wfile.write(b'

Authorization redirect completed. You may ' + b'close this window.

') + with http.server.HTTPServer(('127.0.0.1', listen_port), MyHandler) as httpd: + try: + httpd.handle_request() + except KeyboardInterrupt: + pass + + if not authcode: + sys.exit('Did not obtain an authcode.') + + for k in 'response_type', 'login_hint', 'code_challenge', 'code_challenge_method': + del p[k] + p.update({'grant_type': 'authorization_code', + 'code': authcode, + 'client_secret': registration['client_secret'], + 'code_verifier': verifier}) + print('Exchanging the authorization code for an access token') + try: + response = urllib.request.urlopen(registration['token_endpoint'], + urllib.parse.urlencode(p).encode()) + except urllib.error.HTTPError as err: + print(err.code, err.reason) + response = err + response = response.read() + if args.debug: + print(response) + response = json.loads(response) + if 'error' in response: + print(response['error']) + if 'error_description' in response: + print(response['error_description']) + sys.exit(1) + + elif authflow == 'devicecode': + try: + response = urllib.request.urlopen(registration['devicecode_endpoint'], + urllib.parse.urlencode(p).encode()) + except urllib.error.HTTPError as err: + print(err.code, err.reason) + response = err + response = response.read() + if args.debug: + print(response) + response = json.loads(response) + if 'error' in response: + print(response['error']) + if 'error_description' in response: + print(response['error_description']) + sys.exit(1) + print(response['message']) + del p['scope'] + p.update({'grant_type': 'urn:ietf:params:oauth:grant-type:device_code', + 'client_secret': registration['client_secret'], + 'device_code': response['device_code']}) + interval = int(response['interval']) + print('Polling...', end='', flush=True) + while True: + time.sleep(interval) + print('.', end='', flush=True) + try: + response = urllib.request.urlopen(registration['token_endpoint'], + urllib.parse.urlencode(p).encode()) + except urllib.error.HTTPError as err: + # Not actually always an error, might just mean "keep trying..." + response = err + response = response.read() + if args.debug: + print(response) + response = json.loads(response) + if 'error' not in response: + break + if response['error'] == 'authorization_declined': + print(' user declined authorization.') + sys.exit(1) + if response['error'] == 'expired_token': + print(' too much time has elapsed.') + sys.exit(1) + if response['error'] != 'authorization_pending': + print(response['error']) + if 'error_description' in response: + print(response['error_description']) + sys.exit(1) + print() + + else: + sys.exit(f'ERROR: Unknown OAuth2 flow "{token["authflow"]}. Delete token file and ' + f'start over.') + + update_tokens(response) + + +if not access_token_valid(): + if args.verbose: + print('NOTICE: Invalid or expired access token; using refresh token ' + 'to obtain new access token.') + if not token['refresh_token']: + sys.exit('ERROR: No refresh token. Run script with "--authorize".') + p = baseparams.copy() + p.update({'client_secret': registration['client_secret'], + 'refresh_token': token['refresh_token'], + 'grant_type': 'refresh_token'}) + try: + response = urllib.request.urlopen(registration['token_endpoint'], + urllib.parse.urlencode(p).encode()) + except urllib.error.HTTPError as err: + print(err.code, err.reason) + response = err + response = response.read() + if args.debug: + print(response) + response = json.loads(response) + if 'error' in response: + print(response['error']) + if 'error_description' in response: + print(response['error_description']) + print('Perhaps refresh token invalid. Try running once with "--authorize"') + sys.exit(1) + update_tokens(response) + + +if not access_token_valid(): + sys.exit('ERROR: No valid access token. This should not be able to happen.') + + +if args.verbose: + print('Access Token: ', end='') +print(token['access_token']) + + +def build_sasl_string(user, host, port, bearer_token): + '''Build appropriate SASL string, which depends on cloud server's supported SASL method.''' + if registration['sasl_method'] == 'OAUTHBEARER': + return f'n,a={user},\1host={host}\1port={port}\1auth=Bearer {bearer_token}\1\1' + if registration['sasl_method'] == 'XOAUTH2': + return f'user={user}\1auth=Bearer {bearer_token}\1\1' + sys.exit(f'Unknown SASL method {registration["sasl_method"]}.') + + +if args.test: + errors = False + + imap_conn = imaplib.IMAP4_SSL(registration['imap_endpoint']) + sasl_string = build_sasl_string(token['email'], registration['imap_endpoint'], 993, + token['access_token']) + if args.debug: + imap_conn.debug = 4 + try: + imap_conn.authenticate(registration['sasl_method'], lambda _: sasl_string.encode()) + # Microsoft has a bug wherein a mismatch between username and token can still report a + # successful login... (Try a consumer login with the token from a work/school account.) + # Fortunately subsequent commands fail with an error. Thus we follow AUTH with another + # IMAP command before reporting success. + imap_conn.list() + if args.verbose: + print('IMAP authentication succeeded') + except imaplib.IMAP4.error as e: + print('IMAP authentication FAILED (does your account allow IMAP?):', e) + errors = True + + pop_conn = poplib.POP3_SSL(registration['pop_endpoint']) + sasl_string = build_sasl_string(token['email'], registration['pop_endpoint'], 995, + token['access_token']) + if args.debug: + pop_conn.set_debuglevel(2) + try: + # poplib doesn't have an auth command taking an authenticator object + # Microsoft requires a two-line SASL for POP + # pylint: disable=W0212 + pop_conn._shortcmd('AUTH ' + registration['sasl_method']) + pop_conn._shortcmd(base64.standard_b64encode(sasl_string.encode()).decode()) + if args.verbose: + print('POP authentication succeeded') + except poplib.error_proto as e: + print('POP authentication FAILED (does your account allow POP?):', e.args[0].decode()) + errors = True + + # SMTP_SSL would be simpler but Microsoft does not answer on port 465. + smtp_conn = smtplib.SMTP(registration['smtp_endpoint'], 587) + sasl_string = build_sasl_string(token['email'], registration['smtp_endpoint'], 587, + token['access_token']) + smtp_conn.ehlo('test') + smtp_conn.starttls() + smtp_conn.ehlo('test') + if args.debug: + smtp_conn.set_debuglevel(2) + try: + smtp_conn.auth(registration['sasl_method'], lambda _=None: sasl_string) + if args.verbose: + print('SMTP authentication succeeded') + except smtplib.SMTPAuthenticationError as e: + print('SMTP authentication FAILED:', e) + errors = True + + if errors: + sys.exit(1) diff --git a/home-modules/mutt/neomutt.nix b/home-modules/mutt/neomutt.nix new file mode 100644 index 0000000..6132198 --- /dev/null +++ b/home-modules/mutt/neomutt.nix @@ -0,0 +1,84 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.neomutt + pkgs.isync + pkgs.msmtp + pkgs.notmuch + pkgs.abook + pkgs.urlview + + (pkgs.writeScriptBin "mutt_oauth" (builtins.readFile ./mutt_oauth2.py)) + + ]; + + programs.neomutt = { + enable = true; + package = pkgs.neomutt; + editor = "micro"; + sort = "date"; + sidebar = { + enable = true; + }; + binds = [ + { map = [ "index" ]; key = ""; action = "sidebar-toggle-visible"; } + { map = [ "pager" ]; key = ""; action = "sidebar-toggle-visible"; } + { map = [ "index" ]; key = "\\Cp"; action = "sidebar-prev"; } + { map = [ "pager" ]; key = "\\Cp"; action = "sidebar-prev"; } + { map = [ "index" ]; key = "\\Cn"; action = "sidebar-next"; } + { map = [ "pager" ]; key = "\\Cn"; action = "sidebar-next"; } + { map = [ "index" ]; key = "\\Co"; action = "sidebar-open"; } + { map = [ "pager" ]; key = "\\Co"; action = "sidebar-open"; } + { map = [ "pager" ]; key = ""; action = "previous-line"; } + { map = [ "pager" ]; key = ""; action = "next-line"; } + ]; + + settings = let imapUser = "lennart.kurzweg.lk@gmail.com"; in { + cryptReplysign = true; + cryptVerifySig = true; + editHeaders = true; + from = imapUser; + inherit imapUser; + imapPass = ""; + imapAuthenticators = "oauthbearer:xoauth2"; + imapOAuthRefreshCommand = "mutt_oauth ~/.config/mutt/${imapUser}.tokens"; + smtpUrl = "smtp://lennart.kurzweg.lk@smtp.gmail.com:587/"; + smtpPass = ""; + sslForceTls = true; + realname = "Lennart J. Kurzweg"; + useFrom = true; + timeout = 10; + }; + + # Color Settings + # colors = { + # normal = "white default"; + # attachment = "brightyellow default"; + # hdrdefault = "cyan default"; + # indicator = "black cyan"; + # markers = "brightred default"; + # quoted = "green default"; + # signature = "cyan default"; + # status = "brightgreen blue"; + # tilde = "blue default"; + # tree = "red default"; + # index = [ + # "red default ~P" + # "red default ~D" + # "magenta default ~T" + # ]; + # header = [ + # "brightgreen default ^From:" + # "brightcyan default ^To:" + # "brightcyan default ^Reply-To:" + # "brightcyan default ^Cc:" + # "brightblue default ^Subject:" + # ]; + # body = [ + # "brightred default [\\-\\.+_a-zA-Z0-9]+@[\\-\\.a-zA-Z0-9]+" + # "brightblue default (https?|ftp)://[\\-\\.,/%~_:?&=\\#a-zA-Z0-9]+" + # ]; + # }; + }; +} \ No newline at end of file diff --git a/home-modules/neomutt.nix b/home-modules/neomutt.nix new file mode 100644 index 0000000..689c03e --- /dev/null +++ b/home-modules/neomutt.nix @@ -0,0 +1,84 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.neomutt + pkgs.isync + pkgs.msmtp + pkgs.notmuch + pkgs.abook + pkgs.urlview + + (pkgs.writeScriptBin "mutt_oauth" (builtins.readFile ./scripts/mutt_oauth2.py)) + + ]; + + programs.neomutt = { + enable = true; + package = pkgs.neomutt; + editor = "micro"; + sort = "date"; + sidebar = { + enable = true; + }; + binds = [ + { map = [ "index" ]; key = ""; action = "sidebar-toggle-visible"; } + { map = [ "pager" ]; key = ""; action = "sidebar-toggle-visible"; } + { map = [ "index" ]; key = "\\Cp"; action = "sidebar-prev"; } + { map = [ "pager" ]; key = "\\Cp"; action = "sidebar-prev"; } + { map = [ "index" ]; key = "\\Cn"; action = "sidebar-next"; } + { map = [ "pager" ]; key = "\\Cn"; action = "sidebar-next"; } + { map = [ "index" ]; key = "\\Co"; action = "sidebar-open"; } + { map = [ "pager" ]; key = "\\Co"; action = "sidebar-open"; } + { map = [ "pager" ]; key = ""; action = "previous-line"; } + { map = [ "pager" ]; key = ""; action = "next-line"; } + ]; + + settings = let imapUser = "lennart.kurzweg.lk@gmail.com"; in { + cryptReplysign = true; + cryptVerifySig = true; + editHeaders = true; + from = imapUser; + inherit imapUser; + imapPass = ""; + imapAuthenticators = "oauthbearer:xoauth2"; + imapOAuthRefreshCommand = "mutt_oauth ~/.config/mutt/${imapUser}.tokens"; + smtpUrl = "smtp://lennart.kurzweg.lk@smtp.gmail.com:587/"; + smtpPass = ""; + sslForceTls = true; + realname = "Lennart J. Kurzweg"; + useFrom = true; + timeout = 10; + }; + + # Color Settings + # colors = { + # normal = "white default"; + # attachment = "brightyellow default"; + # hdrdefault = "cyan default"; + # indicator = "black cyan"; + # markers = "brightred default"; + # quoted = "green default"; + # signature = "cyan default"; + # status = "brightgreen blue"; + # tilde = "blue default"; + # tree = "red default"; + # index = [ + # "red default ~P" + # "red default ~D" + # "magenta default ~T" + # ]; + # header = [ + # "brightgreen default ^From:" + # "brightcyan default ^To:" + # "brightcyan default ^Reply-To:" + # "brightcyan default ^Cc:" + # "brightblue default ^Subject:" + # ]; + # body = [ + # "brightred default [\\-\\.+_a-zA-Z0-9]+@[\\-\\.a-zA-Z0-9]+" + # "brightblue default (https?|ftp)://[\\-\\.,/%~_:?&=\\#a-zA-Z0-9]+" + # ]; + # }; + }; +} \ No newline at end of file diff --git a/home-modules/pnx.nix b/home-modules/pnx.nix new file mode 100644 index 0000000..c0f8f3f --- /dev/null +++ b/home-modules/pnx.nix @@ -0,0 +1,30 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.remmina + pkgs.openvpn + + (pkgs.writeShellScriptBin "connect_to_pnx" '' + pushd ~/.ssl/ + sudo openvpn --config /home/nx2/.vpn/ljk-pnx.ovpn --auth-user-pass ~/.vpn/ljk-pnx-pass.txt #gets put there by home-manager + popd + '') + + ]; + + home.file = { + + ".vpn/ljk-pnx-cert.pem".text = secrets.pnxVpn.cert; + ".vpn/ljk-pnx-cert.key".text = secrets.pnxVpn.certKey; + ".vpn/ljk-pnx-ca.pem".text = secrets.pnxVpn.ca; + ".vpn/ljk-pnx.ovpn".text = secrets.pnxVpn.ovpn; + ".vpn/ljk-pnx-pass.txt".text = secrets.pnxVpn.pass; + + # Remmina + ".local/share/remmina/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina; + ".local/share/remmina/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina; + ".local/share/remmina/pnx_rdp_srv-phoenix2_192-168-1-101.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-phoenix2_192-168-1-101.remmina; + ".local/share/remmina/pnx_rdp_srv-remote_192-168-1-21.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-remote_192-168-1-21.remmina; + }; +} \ No newline at end of file diff --git a/home-modules/pnx/pnx.nix b/home-modules/pnx/pnx.nix new file mode 100644 index 0000000..b911350 --- /dev/null +++ b/home-modules/pnx/pnx.nix @@ -0,0 +1,30 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.remmina + pkgs.openvpn + + (pkgs.writeShellScriptBin "connect_to_pnx" '' + pushd ~/.vpn/ + sudo openvpn --config /home/nx2/.vpn/ljk-pnx.ovpn --auth-user-pass ~/.vpn/ljk-pnx-pass.txt #gets put there by home-manager + popd + '') + + ]; + + home.file = { + + ".vpn/ljk-pnx-cert.pem".text = secrets.pnxVpn.cert; + ".vpn/ljk-pnx-cert.key".text = secrets.pnxVpn.certKey; + ".vpn/ljk-pnx-ca.pem".text = secrets.pnxVpn.ca; + ".vpn/ljk-pnx.ovpn".text = secrets.pnxVpn.ovpn; + ".vpn/ljk-pnx-pass.txt".text = secrets.pnxVpn.pass; + + # Remmina + ".local/share/remmina/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina".source = ./pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina; + ".local/share/remmina/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina".source = ./pnx_rdp_srv-phoenix-3_192-168-1-108.remmina; + ".local/share/remmina/pnx_rdp_srv-phoenix2_192-168-1-101.remmina".source = ./pnx_rdp_srv-phoenix2_192-168-1-101.remmina; + ".local/share/remmina/pnx_rdp_srv-remote_192-168-1-21.remmina".source = ./pnx_rdp_srv-remote_192-168-1-21.remmina; + }; +} \ No newline at end of file diff --git a/home-modules/pnx/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina b/home-modules/pnx/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina new file mode 100644 index 0000000..fb55697 --- /dev/null +++ b/home-modules/pnx/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina @@ -0,0 +1,98 @@ +[remmina] +password= +gateway_username= +notes_text= +vc= +window_height=559 +preferipv6=0 +ssh_tunnel_loopback=0 +serialname= +tls-seclevel= +freerdp_log_level=INFO +scale=2 +printer_overrides= +name=srv-phoe3-vmdms +console=0 +colordepth=99 +security= +precommand= +disable_fastpath=0 +postcommand= +left-handed=0 +multitransport=0 +group=pnx +server=192.168.1.104 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +labels= +audio-output= +parallelpath= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +old-license=0 +disconnect-prompt=0 +ssh_tunnel_password= +resolution_mode=2 +assistance_mode=0 +pth= +loadbalanceinfo= +disableautoreconnect=0 +clientbuild= +clientname= +resolution_width=0 +drive= +relax-order-checks=0 +base-cred-for-gw=0 +gateway_domain= +profile-lock=0 +rdp2tcp= +gateway_password= +serialdriver= +rdp_reconnect_attempts= +domain=phoenix2 +smartcardname= +serialpath= +restricted-admin=0 +multimon=0 +exec= +enable-autostart=0 +usb= +shareprinter=0 +network=none +ssh_tunnel_passphrase= +username=wartung +disablepasswordstoring=0 +quality=0 +span=0 +shareparallel=0 +parallelname= +viewmode=1 +ssh_tunnel_auth=0 +keymap= +ssh_tunnel_username= +execpath= +shareserial=0 +resolution_height=0 +timeout= +useproxyenv=0 +sharesmartcard=0 +freerdp_log_filters= +microphone= +dvc= +ssh_tunnel_privatekey= +gwtransp=http +ssh_tunnel_server= +ignore-tls-errors=1 +window_maximize=1 +disable-smooth-scrolling=0 +gateway_usage=0 +rdp_mouse_jitter=No +window_width=459 +no-suppress=0 +sound=off +websockets=0 diff --git a/home-modules/pnx/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina b/home-modules/pnx/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina new file mode 100644 index 0000000..9b0dedd --- /dev/null +++ b/home-modules/pnx/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina @@ -0,0 +1,98 @@ +[remmina] +password= +gateway_username= +notes_text= +window_height=1134 +vc= +scale=2 +ssh_tunnel_loopback=0 +serialname= +preferipv6=0 +tls-seclevel= +websockets=0 +printer_overrides= +name=srv-phoenix-3 +console=0 +colordepth=99 +security= +precommand= +disable_fastpath=0 +postcommand= +left-handed=0 +multitransport=0 +group=pnx +server=192.168.1.108 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +labels= +audio-output= +parallelpath= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +old-license=0 +disconnect-prompt=0 +ssh_tunnel_password= +resolution_mode=2 +assistance_mode=0 +pth= +loadbalanceinfo= +disableautoreconnect=0 +clientbuild= +clientname= +resolution_width=0 +drive= +relax-order-checks=0 +base-cred-for-gw=0 +gateway_domain= +profile-lock=0 +rdp2tcp= +gateway_password= +serialdriver= +rdp_reconnect_attempts= +domain=phoenix2 +multimon=0 +exec= +serialpath= +smartcardname= +username=wartung +restricted-admin=0 +enable-autostart=0 +usb= +network=none +ssh_tunnel_passphrase= +shareprinter=0 +disablepasswordstoring=0 +quality=0 +span=0 +shareparallel=0 +parallelname= +viewmode=1 +ssh_tunnel_auth=0 +keymap= +ssh_tunnel_username= +execpath= +shareserial=0 +resolution_height=0 +timeout= +useproxyenv=0 +sharesmartcard=0 +freerdp_log_filters= +microphone= +dvc= +ssh_tunnel_privatekey= +gwtransp=http +ssh_tunnel_server= +ignore-tls-errors=1 +window_maximize=1 +disable-smooth-scrolling=0 +gateway_usage=0 +rdp_mouse_jitter=No +window_width=939 +no-suppress=0 +freerdp_log_level=INFO +sound=off diff --git a/home-modules/pnx/pnx_rdp_srv-phoenix2_192-168-1-101.remmina b/home-modules/pnx/pnx_rdp_srv-phoenix2_192-168-1-101.remmina new file mode 100644 index 0000000..e1f1f1a --- /dev/null +++ b/home-modules/pnx/pnx_rdp_srv-phoenix2_192-168-1-101.remmina @@ -0,0 +1,98 @@ +[remmina] +password=. +gateway_username= +notes_text= +window_height=1134 +vc= +scale=2 +ssh_tunnel_loopback=0 +serialname= +preferipv6=0 +tls-seclevel= +sound=off +printer_overrides= +name=srv-phoenix2 +console=0 +colordepth=99 +security= +precommand= +disable_fastpath=0 +postcommand= +left-handed=0 +multitransport=0 +group=pnx +server=192.168.1.101 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +labels= +audio-output= +parallelpath= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +old-license=0 +disconnect-prompt=0 +ssh_tunnel_password= +resolution_mode=2 +assistance_mode=0 +pth= +loadbalanceinfo= +disableautoreconnect=0 +clientbuild= +clientname= +resolution_width=0 +drive= +relax-order-checks=0 +base-cred-for-gw=0 +gateway_domain= +profile-lock=0 +rdp2tcp= +gateway_password= +serialdriver= +rdp_reconnect_attempts= +domain=phoenix2 +smartcardname= +exec= +restricted-admin=0 +multimon=0 +serialpath= +enable-autostart=0 +usb= +shareprinter=0 +network=none +ssh_tunnel_passphrase= +username=wartung +disablepasswordstoring=0 +quality=0 +span=0 +shareparallel=0 +parallelname= +viewmode=1 +ssh_tunnel_auth=0 +keymap= +ssh_tunnel_username= +execpath= +shareserial=0 +resolution_height=0 +timeout= +useproxyenv=0 +sharesmartcard=0 +freerdp_log_filters= +microphone= +dvc= +ssh_tunnel_privatekey= +gwtransp=http +ssh_tunnel_server= +ignore-tls-errors=1 +window_maximize=1 +disable-smooth-scrolling=0 +gateway_usage=0 +rdp_mouse_jitter=No +window_width=939 +no-suppress=0 +websockets=0 +freerdp_log_level=INFO diff --git a/home-modules/pnx/pnx_rdp_srv-remote_192-168-1-21.remmina b/home-modules/pnx/pnx_rdp_srv-remote_192-168-1-21.remmina new file mode 100644 index 0000000..cf9e96b --- /dev/null +++ b/home-modules/pnx/pnx_rdp_srv-remote_192-168-1-21.remmina @@ -0,0 +1,95 @@ +[remmina] +password= +gateway_username= +notes_text= +vc= +preferipv6=0 +ssh_tunnel_loopback=0 +serialname= +tls-seclevel= +sound=off +printer_overrides= +name=srv-remote +console=0 +colordepth=99 +security= +precommand= +disable_fastpath=0 +left-handed=0 +postcommand= +multitransport=0 +group=pnx +server=192.168.1.21 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +labels= +audio-output= +parallelpath= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +old-license=0 +ssh_tunnel_password= +resolution_mode=2 +pth= +disableautoreconnect=0 +loadbalanceinfo= +clientbuild= +clientname= +resolution_width=0 +drive= +relax-order-checks=0 +username=wartung +base-cred-for-gw=0 +gateway_domain= +network=none +rdp2tcp= +serialdriver= +rdp_reconnect_attempts= +domain=phoenix2 +profile-lock=0 +restricted-admin=0 +multimon=0 +gateway_password= +exec= +smartcardname= +serialpath= +enable-autostart=0 +usb= +shareprinter=0 +ssh_tunnel_passphrase= +disablepasswordstoring=0 +shareparallel=0 +quality=0 +span=0 +parallelname= +ssh_tunnel_auth=0 +keymap= +ssh_tunnel_username= +execpath= +shareserial=0 +resolution_height=0 +timeout= +useproxyenv=0 +sharesmartcard=0 +freerdp_log_filters= +microphone= +dvc= +ssh_tunnel_privatekey= +gwtransp=http +ssh_tunnel_server= +ignore-tls-errors=1 +disable-smooth-scrolling=0 +gateway_usage=0 +no-suppress=0 +websockets=0 +freerdp_log_level=INFO +window_height=559 +window_maximize=1 +window_width=459 +scale=2 +viewmode=1 diff --git a/home-modules/shell/fish.nix b/home-modules/shell/fish.nix new file mode 100644 index 0000000..7c4c2b0 --- /dev/null +++ b/home-modules/shell/fish.nix @@ -0,0 +1,65 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.fish + + (pkgs.writeShellScriptBin "nxfetch" '' + logo=$(echo -e " + + ⠀⠀⠀⠀⠰⣿⣧⠀⠀⠹⣿⣧⠀⣴⣿⠆⠀⠀⠀⠀ OS + ⠀⠀⠀⣀⣀⣹⣿⣧⣀⣀⠘⣿⣿⣿⠏⠀⠀⠀⠀⠀ DE/WM + ⠀⠀⠼⠿⠿⠿⠿⠿⠿⠿⠦⠘⣿⣿⡀⠀⣼⣧⠀⠀ TERM + ⠀⠀⠀⠀⢠⣶⡶⠀⠀⠀⠀⠀⠈⠿⢁⣼⣿⠋⠀⠀ SHELL + ⢾⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⡷ ISHELL + ⠀⠀⣠⣿⡟⢁⣶⡀⠀⠀⠀⠀⠀⠾⠿⠃⠀⠀⠀⠀ KERNEL + ⠀⠀⢻⡟⠀⠈⢿⣿⡄⠲⣶⣶⣶⣶⣶⣶⣶⡖⠀⠀ EDITOR + ⠀⠀⠀⠀⠀⣰⣿⣿⣿⡄⠉⠉⢻⣿⣏⠉⠉⠀⠀⠀ TFM + ⠀⠀⠀⠀⠰⣿⠟⠀⢻⣿⣆⠀⠀⠻⣿⠆⠀⠀⠀⠀ PROMPT + + " | lolcat --force) + + msg=" + $(echo -e "$logo" | sed -n 3p): $(cat /etc/*-release | grep PRETTY_NAME | cut -c 14- | rev | cut -c 2- | rev) + $(echo -e "$logo" | sed -n 4p): ''${DESKTOP_SESSION^} + $(echo -e "$logo" | sed -n 5p): ''${TERM^} + $(echo -e "$logo" | sed -n 6p): ''${SHELL} + $(echo -e "$logo" | sed -n 7p): fish + $(echo -e "$logo" | sed -n 8p): ''$(uname -r) + $(echo -e "$logo" | sed -n 9p): ''${EDITOR} + $(echo -e "$logo" | sed -n 10p): $(yazi --version) + $(echo -e "$logo" | sed -n 11p): $(starship --version | head -n 1) + " + echo -e "$msg" + '') + ]; + + # bash>>fish is set in users system module + + programs.fish = { + enable = true; + shellAliases = { + ls = "eza --icons --git --smart-group --group-directories-first"; + ll = "eza --icons --git --smart-group --group-directories-first --long"; + la = "eza --icons --git --smart-group --group-directories-first --all"; + lla = "eza --icons --git --smart-group --group-directories-first --all --long"; + lt = "eza --icons --git --smart-group --group-directories-first --long --tree"; + ltd = "eza --icons --git --smart-group --group-directories-first --long --tree -D"; + lt2 = "eza --icons --git --smart-group --group-directories-first --long --tree -L 2"; + sr = "sudo reboot"; + nf = "neofetch"; + nxf = "nxfetch"; + nn = "nano"; + m = "micro"; + c = "codium"; + code = "codium"; + # ya = "yazi"; # function + nxfiglet = "figlet"; + }; + interactiveShellInit = '' + set -g fish_greeting + nxfetch + ${pkgs.starship}/bin/starship init fish | source + ''; + }; +} \ No newline at end of file diff --git a/home-modules/shell/starship.nix b/home-modules/shell/starship.nix new file mode 100644 index 0000000..78505b1 --- /dev/null +++ b/home-modules/shell/starship.nix @@ -0,0 +1,108 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.starship + ]; + + ## gets sourced in fish.nix + + + programs.starship = { + enable = true; + settings = { + add_newline = false; + format = "$jobs\$battery\$username\$hostname\$localip\$shlvl\$singularity\$kubernetes\$directory\$vcsh\$git_branch\$git_commit\$git_state\$git_metrics\$git_status\$hg_branch\$docker_context\$package\$c\$cmake\$cobol\$daml\$dart\$deno\$dotnet\$elixir\$elm\$erlang\$golang\$haskell\$helm\$java\$julia\$kotlin\$lua\$nim\$nodejs\$ocaml\$perl\$php\$pulumi\$purescript\$python\$raku\$rlang\$red\$ruby\$rust\$scala\$swift\$terraform\$vlang\$vagrant\$zig\$buf\$nix_shell\$conda\$meson\$spack\$memory_usage\$aws\$gcloud\$openstack\$azure\$env_var\$crystal\$custom\$sudo\$cmd_duration\$time\$status\$container\$shell\$character"; + aws.format = "[\\[$symbol($profile)(\\($region\\))(\\[$duration\\])\\]]($style)"; + bun.format = "[\\[$symbol($version)\\]]($style)"; + c.format = "[\\[$symbol($version(-$name))\\]]($style)"; + cmake.format = "[\\[$symbol($version)\\]]($style)"; + cmd_duration.format = "[\\[󰔛 $duration\\]]($style)"; + cobol.format = "[\\[$symbol($version)\\]]($style)"; + conda.format = "[\\[$symbol$environment\\]]($style)"; + crystal.format = "[\\[$symbol($version)\\]]($style)"; + daml.format = "[\\[$symbol($version)\\]]($style)"; + dart.format = "[\\[$symbol($version)\\]]($style)"; + deno.format = "[\\[$symbol($version)\\]]($style)"; + docker_context.format = "[\\[$symbol$context\\]]($style)"; + dotnet.format = "[\\[$symbol($version)(🎯 $tfm)\\]]($style)"; + elixir.format = "[\\[$symbol($version \\(OTP $otp_version\\))\\]]($style)"; + elm.format = "[\\[$symbol($version)\\]]($style)"; + erlang.format = "[\\[$symbol($version)\\]]($style)"; + gcloud.format = "[\\[$symbol$account(@$domain)(\\($region\\))\\]]($style)"; + git_branch = { + format = "[\\[$symbol$branch:]($style)"; + style = "bold green"; + }; + git_status = { + format = "([$all_status$ahead_behind]($style))(bold green)[\\]]($style)"; + style = "blue yellow"; + }; + golang.format = "[\\[$symbol($version)\\]]($style)"; + haskell.format = "[\\[$symbol($version)\\]]($style)"; + helm.format = "[\\[$symbol($version)\\]]($style)"; + hg_branch.format = "[\\[$symbol$branch\\]]($style)"; + java.format = "[\\[$symbol($version)\\]]($style)"; + julia.format = "[\\[$symbol($version)\\]]($style)"; + kotlin.format = "[\\[$symbol($version)\\]]($style)"; + kubernetes.format = "[\\[$symbol$context( \\($namespace\\))\\]]($style)"; + lua.format = "[\\[$symbol($version)\\]]($style)"; + memory_usage.format = "[\\[$symbol[$ram( | $swap)\\]]($style)"; + meson.format = "[\\[$symbol$project\\]]($style)"; + nim.format = "[\\[$symbol($version)\\]]($style)"; + nix_shell.format = "[\\[$symbol$state( \\($name\\))\\]]($style)"; + nodejs.format = "[\\[$symbol($version)\\]]($style)"; + ocaml.format = "[\\[$symbol($version)(\\($switch_indicator$switch_name\\))\\]]($style)"; + openstack.format = "[\\[$symbol$cloud(\\($project\\))\\]]($style)"; + package.format = "[\\[$symbol$version\\]]($style)"; + perl.format = "[\\[$symbol($version)\\]]($style)"; + php.format = "[\\[$symbol($version)\\]]($style)"; + pulumi.format = "[\\[$symbol$stack\\]]($style)"; + purescript.format = "[\\[$symbol($version)\\]]($style)"; + python = { + format = ''[\[''${symbol}''${pyenv_prefix}''${version}$virtualenv\]]($style)''; + symbol = " "; + }; + raku.format = "[\\[$symbol($version-$vm_version)\\]]($style)"; + red.format = "[\\[$symbol($version)\\]]($style)"; + ruby.format = "[\\[$symbol($version)\\]]($style)"; + rust.format = "[\\[$symbol($version)\\]]($style)"; + scala.format = "[\\[$symbol($version)\\]]($style)"; + spack.format = "[\\[$symbol$environment\\]]($style)"; + sudo.format = "[\\[$symbol]\\]"; + swift.format = "[\\[$symbol($version)\\]]($style)"; + terraform.format = "[\\[$symbol$workspace\\]]($style)"; + time.format = "[\\[$time\\]]($style)"; + username.format = "[\\[$user\\]]($style)"; + vagrant.format = "[\\[$symbol($version)\\]]($style)"; + vlang.format = "[\\[$symbol($version)\\]]($style)"; + zig.format = "[\\[$symbol($version)\\]]($style)"; + directory = { + format = "[\\[]($style)[$lock_symbol]($lock_style)[$path\\]]($style)"; + style = "cyan bold"; + }; + character = { + format = "$symbol"; + success_symbol = "[\\[󰽧\\]](bold white) "; + error_symbol = "[\\[\\]](bold red) "; + vimcmd_symbol = "[\\[\\]](bold green) "; + vimcmd_replace_one_symbol = "[\\[1\\]](bold green) "; + vimcmd_replace_symbol = "[\\[R\\]](bold green) "; + vimcmd_visual_symbol = "[\\[V\\]](bold green) "; + }; + battery.format = "[\\[$symbol$percentage\\]]($style)"; + shlvl.format = "[\\[$symbol$shlvl\\]]($style)"; + singularity.format = "[\\[$symbol\\[$env\\]\\]]($style)"; + jobs = { + format = "[\\[$symbol $number\\]]($style)"; + number_threshold = 1; + }; + vcsh.format = "[\\[vcsh [$symbol$repo\\]]($style)"; + hostname = { + format = "[\\[$ssh_symbol$hostname\\]]($style)"; + ssh_symbol = "爵"; + ssh_only = true; + }; + }; + }; +} \ No newline at end of file diff --git a/home-modules/shell/yazi.nix b/home-modules/shell/yazi.nix new file mode 100644 index 0000000..18547a7 --- /dev/null +++ b/home-modules/shell/yazi.nix @@ -0,0 +1,51 @@ + +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.yazi + ]; + + programs.yazi = { + enable = true; + enableFishIntegration = true; + settings = { + manager = { + layout = [1 3 4]; + sort_by = "natural"; + sort_sensitive = true; + sort_reverse = false; + sort_dir_first = true; + linemode = "size"; + show_hidden = true; + show_symlink = true; + }; + opener = { + edit = [ + { exec = ''micro "$@"''; desc = "micro"; block = true;} + { exec = ''codium "$@"''; orphan = true;} + { exec = ''nano "$@"''; desc = "nano"; block = true;} + { exec = ''sudo nano "$@"''; desc = "sudo nano"; block = true;} + ]; + play = [ + { exec = ''mpv "$@"''; } + { exec = ''mediainfo "$1"; echo "Press enter to exit"; read''; block = true; desc = "Show mediainfo";} + ]; + archive = [ + { exec = ''unar "$1"''; desc = "Extract here"; } + ]; + image = [ + { exec = ''imv "$@"''; desc = "imv";} + { exec = ''gimp "$@"''; desc = "gimp";} + ]; + font = [ + { exec = ''fontpreview "$@"''; desc = "fontpreview"; } + ]; + document = [ + { exec = ''zathura "$@"''; desc = "zathura"; } + { exec = ''firefox "$@"''; desc = "firefox"; } + ]; + }; + }; + }; +} \ No newline at end of file diff --git a/home-modules/ssh.nix b/home-modules/ssh.nix new file mode 100644 index 0000000..8b77116 --- /dev/null +++ b/home-modules/ssh.nix @@ -0,0 +1,28 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + + + + home.file.".ssh/config".text = '' + HOST nxace + HostName nx2.site + User nx2 + Port 50022 + + HOST nxacel + HostName 192.168.178.32 + User nx2 + Port 50022 + + HOST nxrpi + HostName nx2.site + User pi + Port 50023 + + HOST nxrpil + HostName 192.168.178.31 + User pi + Port 50023 + ''; +} \ No newline at end of file diff --git a/home-modules/theme/gtk.nix b/home-modules/theme/gtk.nix new file mode 100644 index 0000000..c43dbe4 --- /dev/null +++ b/home-modules/theme/gtk.nix @@ -0,0 +1,51 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.gnome.gnome-themes-extra + pkgs.gnome.adwaita-icon-theme + pkgs.gnome.gnome-tweaks + pkgs.gtk3 + pkgs.gtk4 + pkgs.lxappearance + ]; + + home.sessionVariables.GTK_THEME = "Adwaita-Dark"; + + gtk = { + enable = true; + theme = { + name = "Adwaita-Dark"; + package = pkgs.gnome.gnome-themes-extra; + }; + gtk3.extraConfig = { + Settings = '' + gtk-application-prefer-dark-theme=1 + ''; + }; + + gtk4.extraConfig = { + Settings = '' + gtk-application-prefer-dark-theme=1 + ''; + }; + }; + + # GTK4 + xdg.configFile = { + "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets"; + "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css"; + "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css"; + }; + + + dconf = { + enable = true; + settings = { + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + gtk-theme = "Adwaita-Dark"; + }; + }; + }; +} \ No newline at end of file diff --git a/home-modules/theme/qt.nix b/home-modules/theme/qt.nix new file mode 100644 index 0000000..52aded9 --- /dev/null +++ b/home-modules/theme/qt.nix @@ -0,0 +1,7 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + qt = { + platformTheme = "gtk"; + }; +} \ No newline at end of file diff --git a/home-modules/vscode.nix b/home-modules/vscode.nix new file mode 100644 index 0000000..42233e2 --- /dev/null +++ b/home-modules/vscode.nix @@ -0,0 +1,78 @@ + +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + home.packages = [ + pkgs.vscodium + ]; + + imports = [ + # Make vscode settings writable + (import (builtins.fetchurl { + url = "https://gist.githubusercontent.com/piousdeer/b29c272eaeba398b864da6abf6cb5daa/raw/41e569ba110eb6ebbb463a6b1f5d9fe4f9e82375/mutability.nix"; + sha256 = "4b5ca670c1ac865927e98ac5bf5c131eca46cc20abf0bd0612db955bfc979de8"; + }) { inherit config lib; }) + + (import (builtins.fetchurl { + url = "https://gist.githubusercontent.com/piousdeer/b29c272eaeba398b864da6abf6cb5daa/raw/41e569ba110eb6ebbb463a6b1f5d9fe4f9e82375/vscode.nix"; + sha256 = "fed877fa1eefd94bc4806641cea87138df78a47af89c7818ac5e76ebacbd025f"; + }) { inherit config lib pkgs; }) + ]; + + programs.vscode = { + enable = true; + package = pkgs.vscodium; + extensions = with pkgs.vscode-extensions; [ + jnoortheen.nix-ide + viktorqvarfordt.vscode-pitch-black-theme + ms-python.python + ms-python.black-formatter + redhat.vscode-yaml + redhat.vscode-xml + ms-python.python + mhutchie.git-graph + github.vscode-pull-request-github + esbenp.prettier-vscode + gencer.html-slim-scss-css-class-completion + donjayamanne.githistory + mads-hartmann.bash-ide-vscode + + #jeanp413.open-remote-ssh + # ms-vscode-remote.remote-ssh + # ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ + # { + # name = "remote-ssh-edit"; + # publisher = "ms-vscode-remote"; + # version = "0.47.2"; + # sha256 = "1hp6gjh4xp2m1xlm1jsdzxw9d8frkiidhph6nvl24d0h8z34w49g"; + # } + ]; + userSettings = { + workbench.colorTheme = "Just Black"; + editor.fontFamily = "'CaskaydiaCove Nerd Font', 'monospace', monospace"; + }; + enableUpdateCheck = false; + enableExtensionUpdateCheck = false; + keybindings = [ + { + key = "ctrl+d"; + command = "editor.action.deleteLines"; + when = "textInputFocus"; + } + { + key = "ctrl+shift+d"; + command = "editor.action.duplicateSelection"; + when = "textInputFocus"; + } + { # unset so that ctrl d is not set twice + key = ""; + command = "editor.action.addSelectionToNextFindMatch"; + when = "editorFocus"; + } + { # unset so that ctrl shift d is not set twice + key = ""; + command = "workbench.view.debug"; + } + ]; + }; +} \ No newline at end of file diff --git a/home.nix b/home.nix index 0a01d85..edc4716 100644 --- a/home.nix +++ b/home.nix @@ -1,92 +1,62 @@ -{ config, pkgs, lib, system, allowed, secrets, ... }: - +{ config, pkgs, lib, system, user, allowed, secrets, ... }: { imports = [ - # Make vscode settings writable - (import (builtins.fetchurl { - url = "https://gist.githubusercontent.com/piousdeer/b29c272eaeba398b864da6abf6cb5daa/raw/41e569ba110eb6ebbb463a6b1f5d9fe4f9e82375/mutability.nix"; - sha256 = "4b5ca670c1ac865927e98ac5bf5c131eca46cc20abf0bd0612db955bfc979de8"; - }) { inherit config lib; }) - - (import (builtins.fetchurl { - url = "https://gist.githubusercontent.com/piousdeer/b29c272eaeba398b864da6abf6cb5daa/raw/41e569ba110eb6ebbb463a6b1f5d9fe4f9e82375/vscode.nix"; - sha256 = "fed877fa1eefd94bc4806641cea87138df78a47af89c7818ac5e76ebacbd025f"; - }) { inherit config lib pkgs; }) + ./home-modules/vscode.nix + ./home-modules/mutt/neomutt.nix + ./home-modules/gestures.nix + + ./home-modules/pnx.nix + # ./home-modules/hsmw.nix + + ./home-modules/hyprland/hyprland.nix + ./home-modules/hyprland/hyprland-autoname-workspaces.nix + + ./home-modules/shell/fish.nix + ./home-modules/shell/starship.nix + ./home-modules/shell/yazi.nix + + ./home-modules/ssh.nix + ./home-modules/git.nix + + ./home-modules/theme/gtk.nix + ./home-modules/theme/qt.nix ]; - home.username = "nx2"; home.homeDirectory = "/home/nx2"; - home.stateVersion = "23.11"; - nixpkgs.config = { allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) allowed.unfree-packages; permittedInsecurePackages = allowed.inecure-packages; }; - - - home.packages = with pkgs; [ firefox chromium chatterino2 - vscodium gimp inkscape + gimp inkscape kitty - zathura remmina + zathura #vesktop thunderbird element-desktop # zoom-us + obsidian spotify spicetify-cli obs-studio bitwarden - hyprland-protocols waybar swww hyprland-autoname-workspaces rofi wlogout imv mpv + + waybar swww rofi wlogout + + imv mpv mediainfo exiftool ffmpeg pavucontrol fontpreview gtk2fontsel - lynx tldr fzf figlet delta ripgrep lolcat - libinput-gestures dotool brightnessctl wev gnome.nautilus gnome.gnome-themes-extra gnome.adwaita-icon-theme gnome.gnome-tweaks gtk3 gtk4 lxappearance + lynx bat du-dust eza neofetch zoxide tldr fzf figlet delta ripgrep lolcat + brightnessctl wev element sssnake pipes - - # # You can also create simple shell scripts directly inside your - # # configuration. For example, this adds a command 'my-hello' to your - # # environment: - (writeShellScriptBin "connect_to_pnx" '' - pushd ~/.ssl/ - sudo openvpn --config /home/nx2/.ssl/ljk-pnx.ovpn --auth-user-pass ~/.ssl/ljk-pnx-pass.txt #gets put there by home-manager - popd - '') - + (pkgs.python3.withPackages (python-pkgs: [ + python-pkgs.pandas + python-pkgs.requests + python-pkgs.ipython + ])) (writeShellScriptBin "nxrbs-nix" '' set -e pushd ~/.nix-dots/ git diff - '') - - (writeShellScriptBin "nxfetch" '' - logo=$(echo -e " - - ⠀⠀⠀⠀⠰⣿⣧⠀⠀⠹⣿⣧⠀⣴⣿⠆⠀⠀⠀⠀ OS - ⠀⠀⠀⣀⣀⣹⣿⣧⣀⣀⠘⣿⣿⣿⠏⠀⠀⠀⠀⠀ DE/WM - ⠀⠀⠼⠿⠿⠿⠿⠿⠿⠿⠦⠘⣿⣿⡀⠀⣼⣧⠀⠀ TERM - ⠀⠀⠀⠀⢠⣶⡶⠀⠀⠀⠀⠀⠈⠿⢁⣼⣿⠋⠀⠀ SHELL - ⢾⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⡷ ISHELL - ⠀⠀⣠⣿⡟⢁⣶⡀⠀⠀⠀⠀⠀⠾⠿⠃⠀⠀⠀⠀ KERNEL - ⠀⠀⢻⡟⠀⠈⢿⣿⡄⠲⣶⣶⣶⣶⣶⣶⣶⡖⠀⠀ EDITOR - ⠀⠀⠀⠀⠀⣰⣿⣿⣿⡄⠉⠉⢻⣿⣏⠉⠉⠀⠀⠀ TFM - ⠀⠀⠀⠀⠰⣿⠟⠀⢻⣿⣆⠀⠀⠻⣿⠆⠀⠀⠀⠀ PROMPT - - " | lolcat --force) - - msg=" - $(echo -e "$logo" | sed -n 3p): $(cat /etc/*-release | grep PRETTY_NAME | cut -c 14- | rev | cut -c 2- | rev) - $(echo -e "$logo" | sed -n 4p): ''${DESKTOP_SESSION^} - $(echo -e "$logo" | sed -n 5p): ''${TERM^} - $(echo -e "$logo" | sed -n 6p): ''${SHELL} - $(echo -e "$logo" | sed -n 7p): fish - $(echo -e "$logo" | sed -n 8p): ''$(uname -r) - $(echo -e "$logo" | sed -n 9p): ''${EDITOR} - $(echo -e "$logo" | sed -n 10p): $(yazi --version) - $(echo -e "$logo" | sed -n 11p): $(starship --version | head -n 1) - " - echo -e "$msg" - '') - # only works on spec arch, chage url for others (stdenv.mkDerivation { name = "easycommit"; @@ -103,29 +73,7 @@ chmod +x $out/bin/easycommit ''; }) - - - ]; - - - xdg.mimeApps = { - enable = true; - defaultApplications = { - "default-web-browser" = [ "firefox.desktop" ]; - "text/html" = [ "firefox.desktop" ]; - "x-scheme-handler/http" = [ "firefox.desktop" ]; - "x-scheme-handler/https" = [ "firefox.desktop" ]; - "x-scheme-handler/about" = [ "firefox.desktop" ]; - "x-scheme-handler/unknown" = [ "firefox.desktop" ]; - "image/png" = "imv.desktop"; - "image/gif" = "imv.desktop"; - }; - }; - - - - # systemd.user.services = { # ydotoold = { # Unit = { @@ -136,149 +84,13 @@ # Service = { # ExecStart = "/run/current-system/sw/bin/ydotoold --socket-path /tmp/ydotool_socket "; # }; - # Install = { # WantedBy = ["default.target"]; # }; # }; # }; - - home.file = { - - ".vpn/ljk-pnx-cert.pem".text = secrets.pnxVpn.cert; - ".vpn/ljk-pnx-cert.key".text = secrets.pnxVpn.certKey; - ".vpn/ljk-pnx-ca.pem".text = secrets.pnxVpn.ca; - ".vpn/ljk-pnx.ovpn".text = secrets.pnxVpn.ovpn; - ".vpn/ljk-pnx-pass.txt".text = secrets.pnxVpn.pass; - - - # ".config/libinput/gestures".text = '' - # # Swipe threshold (0-100) - # swipe_threshold 0 - - # # Gestures - # gesture swipe left 3 ydotool key 276:1 276:0 - # gesture swipe right 3 ydotool key 275:1 275:0 - # '' - ".config/libinput/gestures".text = '' - # Swipe threshold (0-100) - swipe_threshold 0 - - # Gestures - gesture swipe left 3 echo key k:276 | dotool - gesture swipe right 3 echo key k:275 | dotool - ''; - - ".config/hyprland-autoname-workspaces/config.toml".text = '' - version = "1.1.13" - - [class] - Signal = "󱅵" - DEFAULT = "{class}" - libreoffice-writer = "" - pavucontrol = "󰕾" - "epicgameslauncher.exe" = "󰯷" - "riotclientux.exe" = "󰰌" - "[Cc]ode" = "󰨞" - VirtualBox = "" - KiCad = "" - Gimp = "" - code-oss = "󰨞" - VSCodium = "󰨞" - Alacritty = "" - kitty = "" - vesktop = "󰙯" - "cyberpunk2077.exe" = "󰾲" - "Tor Browser" = "󰾔" - "[Tt]hunderbird" = "" - Element = "󰘨" - blueman-manager = "󰂯" - obsidian = "󰠮" - libreoffice-calc = "" - zoom = "󰬡" - mpv = "" - chatterino = "" - "com.obsproject.Studio" = "" - "leagueclientux.exe" = "󰰌" - "[sS]potify" = "" - "org.remmina.Remmina" = "󰢹" - steam = "󰓓" - "galaxyclient.exe" = "󰮡" - "[Ff]irefox" = "󰈹" - pcbnew = "" - ".*.exe" = "" - Chromium = "" - virt-manager = "" - Bitwarden = "" - "[tT]hunar" = "" - zathura = "󰈦" - discord = "󰙯" - "VirtualBox Manager" = "" - "org.inkscape.Inkscape" = "󰕙" - "VirtualBox Machine" = "" - lutris = "󰊗" - "[gG]imp-.*" = "" - - [class_active] - "(?i)ExampleOneTerm" = "icon" - - [initial_class] - - [initial_class_active] - - [workspaces_name] - 10 = "ten" - 4 = "four" - 8 = "eight" - 9 = "nine" - 6 = "six" - 1 = "one" - 3 = "three" - 2 = "two" - 0 = "zero" - 7 = "seven" - 5 = "five" - - [title_in_class] - [title_in_class_active] - [title_in_initial_class] - [title_in_initial_class_active] - [initial_title_in_class] - [initial_title_in_class_active] - [initial_title_in_initial_class] - [initial_title_in_initial_class_active] - - [exclude] - "(?i)fcitx" = ".*" - aProgram = "^$" - "ueberzug.*" = "" - "" = "^$" - "[Ss]team" = "^(Friends List.*)?$" - "explorer.exe" = ".*" - "(?i)TestApp" = "" - - [format] - dedup = false - dedup_inactive_fullscreen = false - delim = " " - workspace = "{id}: {clients}" - workspace_empty = "{id}" - client = "{icon}" - client_fullscreen = "{icon}" - client_active = "{icon}" - client_dup = "{icon}{counter_sup}" - client_dup_active = "*{icon}*{delim}{icon}{counter_unfocused_sup}" - client_dup_fullscreen = "[{icon}]{delim}{icon}{counter_unfocused_sup}" - ''; - # Remmina - ".local/share/remmina/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-phoe3-vmdms_192-168-1-104.remmina; - ".local/share/remmina/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-phoenix-3_192-168-1-108.remmina; - ".local/share/remmina/pnx_rdp_srv-phoenix2_192-168-1-101.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-phoenix2_192-168-1-101.remmina; - ".local/share/remmina/pnx_rdp_srv-remote_192-168-1-21.remmina".source = ./secrets/pnx-vpn/pnx_rdp_srv-remote_192-168-1-21.remmina; - }; - # Home Manager can also manage your environment variables through # 'home.sessionVariables'. If you don't want to manage your shell through Home # Manager then you have to manually source 'hm-session-vars.sh' located at @@ -290,18 +102,12 @@ # # /etc/profiles/per-user/nx2/etc/profile.d/hm-session-vars.sh # - # home.sessionVariables = { - systemd.user.sessionVariables = { - EDITOR = "micro"; - BROWSER = "firefox"; - # YDOTOOL_SOCKET = "/tmp/ydotool_socket"; + home.sessionVariables = { + XDG_CONFIG_HOME = "$HOME/.config"; + XDG_DATA_HOME = "$HOME/.local/share"; + XDG_CACHE_HOME = "$HOME/."; + XDG_STATE_HOME = "$HOME/.local/state"; }; - - - - - - programs.git = { enable = true; userName = "nx2"; @@ -316,277 +122,28 @@ }; }; }; - #https://github.com/NixOS/nixpkgs/blob/592047fc9e4f7b74a4dc85d1b9f5243dfe4899e3/pkgs/applications/editors/vscode/extensions/default.nix#L1539 - programs.vscode = { + + xdg = { enable = true; - package = pkgs.vscodium; - extensions = with pkgs.vscode-extensions; [ - jnoortheen.nix-ide - viktorqvarfordt.vscode-pitch-black-theme - ms-python.python - ms-python.black-formatter - redhat.vscode-yaml - redhat.vscode-xml - ms-python.python - mhutchie.git-graph - github.vscode-pull-request-github - esbenp.prettier-vscode - gencer.html-slim-scss-css-class-completion - donjayamanne.githistory - mads-hartmann.bash-ide-vscode - - #jeanp413.open-remote-ssh - # ms-vscode-remote.remote-ssh - # ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ - # { - # name = "remote-ssh-edit"; - # publisher = "ms-vscode-remote"; - # version = "0.47.2"; - # sha256 = "1hp6gjh4xp2m1xlm1jsdzxw9d8frkiidhph6nvl24d0h8z34w49g"; - # } - ]; - userSettings = { - workbench.colorTheme = "Just Black"; - editor.fontFamily = "'CaskaydiaCove Nerd Font', 'monospace', monospace"; - }; - enableUpdateCheck = false; - enableExtensionUpdateCheck = false; - keybindings = [ - { - key = "ctrl+d"; - command = "editor.action.deleteLines"; - when = "textInputFocus"; - } - { - key = "ctrl+shift+d"; - command = "editor.action.duplicateSelection"; - when = "textInputFocus"; - } - { # unset so that ctrl d is not set twice - key = ""; - command = "editor.action.addSelectionToNextFindMatch"; - when = "editorFocus"; - } - { # unset so that ctrl shift d is not set twice - key = ""; - command = "workbench.view.debug"; - } - ]; - }; - - programs.fish = { - enable = true; - shellAliases = { - ls = "eza --icons --git --smart-group --group-directories-first"; - ll = "eza --icons --git --smart-group --group-directories-first --long"; - la = "eza --icons --git --smart-group --group-directories-first --all"; - lla = "eza --icons --git --smart-group --group-directories-first --all --long"; - lt = "eza --icons --git --smart-group --group-directories-first --long --tree"; - ltd = "eza --icons --git --smart-group --group-directories-first --long --tree -D"; - lt2 = "eza --icons --git --smart-group --group-directories-first --long --tree -L 2"; - sr = "sudo reboot"; - nf = "neofetch"; - nxf = "nxfetch"; - nn = "nano"; - m = "micro"; - c = "codium"; - code = "codium"; - # ya = "yazi"; # function - nxfiglet = "figlet"; - }; - functions = { - ya = { - description = "yazi follow directory wrapper"; - body = '' - set tmp (mktemp -t "yazi-cwd.XXXXX") - yazi $argv --cwd-file="$tmp" - if set cwd (cat -- "$tmp"); and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ] - cd -- "$cwd" - end - rm -f -- "$tmp" - ''; - }; - }; - interactiveShellInit = '' - set -g fish_greeting - nxfetch - ${pkgs.starship}/bin/starship init fish | source - ''; - }; - - - - programs.starship = { - enable = true; - settings = { - add_newline = false; - format = "$jobs\$battery\$username\$hostname\$localip\$shlvl\$singularity\$kubernetes\$directory\$vcsh\$git_branch\$git_commit\$git_state\$git_metrics\$git_status\$hg_branch\$docker_context\$package\$c\$cmake\$cobol\$daml\$dart\$deno\$dotnet\$elixir\$elm\$erlang\$golang\$haskell\$helm\$java\$julia\$kotlin\$lua\$nim\$nodejs\$ocaml\$perl\$php\$pulumi\$purescript\$python\$raku\$rlang\$red\$ruby\$rust\$scala\$swift\$terraform\$vlang\$vagrant\$zig\$buf\$nix_shell\$conda\$meson\$spack\$memory_usage\$aws\$gcloud\$openstack\$azure\$env_var\$crystal\$custom\$sudo\$cmd_duration\$time\$status\$container\$shell\$character"; - aws.format = "[\\[$symbol($profile)(\\($region\\))(\\[$duration\\])\\]]($style)"; - bun.format = "[\\[$symbol($version)\\]]($style)"; - c.format = "[\\[$symbol($version(-$name))\\]]($style)"; - cmake.format = "[\\[$symbol($version)\\]]($style)"; - cmd_duration.format = "[\\[󰔛 $duration\\]]($style)"; - cobol.format = "[\\[$symbol($version)\\]]($style)"; - conda.format = "[\\[$symbol$environment\\]]($style)"; - crystal.format = "[\\[$symbol($version)\\]]($style)"; - daml.format = "[\\[$symbol($version)\\]]($style)"; - dart.format = "[\\[$symbol($version)\\]]($style)"; - deno.format = "[\\[$symbol($version)\\]]($style)"; - docker_context.format = "[\\[$symbol$context\\]]($style)"; - dotnet.format = "[\\[$symbol($version)(🎯 $tfm)\\]]($style)"; - elixir.format = "[\\[$symbol($version \\(OTP $otp_version\\))\\]]($style)"; - elm.format = "[\\[$symbol($version)\\]]($style)"; - erlang.format = "[\\[$symbol($version)\\]]($style)"; - gcloud.format = "[\\[$symbol$account(@$domain)(\\($region\\))\\]]($style)"; - git_branch = { - format = "[\\[$symbol$branch:]($style)"; - style = "bold green"; - }; - git_status = { - format = "([$all_status$ahead_behind]($style))(bold green)[\\]]($style)"; - style = "blue yellow"; - }; - golang.format = "[\\[$symbol($version)\\]]($style)"; - haskell.format = "[\\[$symbol($version)\\]]($style)"; - helm.format = "[\\[$symbol($version)\\]]($style)"; - hg_branch.format = "[\\[$symbol$branch\\]]($style)"; - java.format = "[\\[$symbol($version)\\]]($style)"; - julia.format = "[\\[$symbol($version)\\]]($style)"; - kotlin.format = "[\\[$symbol($version)\\]]($style)"; - kubernetes.format = "[\\[$symbol$context( \\($namespace\\))\\]]($style)"; - lua.format = "[\\[$symbol($version)\\]]($style)"; - memory_usage.format = "[\\[$symbol[$ram( | $swap)\\]]($style)"; - meson.format = "[\\[$symbol$project\\]]($style)"; - nim.format = "[\\[$symbol($version)\\]]($style)"; - nix_shell.format = "[\\[$symbol$state( \\($name\\))\\]]($style)"; - nodejs.format = "[\\[$symbol($version)\\]]($style)"; - ocaml.format = "[\\[$symbol($version)(\\($switch_indicator$switch_name\\))\\]]($style)"; - openstack.format = "[\\[$symbol$cloud(\\($project\\))\\]]($style)"; - package.format = "[\\[$symbol$version\\]]($style)"; - perl.format = "[\\[$symbol($version)\\]]($style)"; - php.format = "[\\[$symbol($version)\\]]($style)"; - pulumi.format = "[\\[$symbol$stack\\]]($style)"; - purescript.format = "[\\[$symbol($version)\\]]($style)"; - python = { - format = ''[\\[''${symbol}''${pyenv_prefix}(''${version})(\\($virtualenv\\))\\]]($style)''; - symbol = " "; - }; - raku.format = "[\\[$symbol($version-$vm_version)\\]]($style)"; - red.format = "[\\[$symbol($version)\\]]($style)"; - ruby.format = "[\\[$symbol($version)\\]]($style)"; - rust.format = "[\\[$symbol($version)\\]]($style)"; - scala.format = "[\\[$symbol($version)\\]]($style)"; - spack.format = "[\\[$symbol$environment\\]]($style)"; - sudo.format = "[\\[$symbol]\\]"; - swift.format = "[\\[$symbol($version)\\]]($style)"; - terraform.format = "[\\[$symbol$workspace\\]]($style)"; - time.format = "[\\[$time\\]]($style)"; - username.format = "[\\[$user\\]]($style)"; - vagrant.format = "[\\[$symbol($version)\\]]($style)"; - vlang.format = "[\\[$symbol($version)\\]]($style)"; - zig.format = "[\\[$symbol($version)\\]]($style)"; - directory = { - format = "[\\[]($style)[$lock_symbol]($lock_style)[$path\\]]($style)"; - style = "cyan bold"; - }; - character = { - format = "$symbol"; - success_symbol = "[\\[󰽧\\]](bold white) "; - error_symbol = "[\\[\\]](bold red) "; - vimcmd_symbol = "[\\[\\]](bold green) "; - vimcmd_replace_one_symbol = "[\\[1\\]](bold green) "; - vimcmd_replace_symbol = "[\\[R\\]](bold green) "; - vimcmd_visual_symbol = "[\\[V\\]](bold green) "; - }; - battery.format = "[\\[$symbol$percentage\\]]($style)"; - shlvl.format = "[\\[$symbol$shlvl\\]]($style)"; - singularity.format = "[\\[$symbol\\[$env\\]\\]]($style)"; - jobs = { - format = "[\\[$symbol $number\\]]($style)"; - number_threshold = 1; - }; - vcsh.format = "[\\[vcsh [$symbol$repo\\]]($style)"; - hostname = { - format = "[\\[$ssh_symbol$hostname\\]]($style)"; - ssh_symbol = "爵"; - ssh_only = true; + configHome = /home/${user}/.config; + cacheHome = /home/${user}/.cache; + mimeApps = { + enable = true; + defaultApplications = { + "default-web-browser" = [ "firefox.desktop" ]; + "text/html" = [ "firefox.desktop" ]; + "x-scheme-handler/http" = [ "firefox.desktop" ]; + "x-scheme-handler/https" = [ "firefox.desktop" ]; + "x-scheme-handler/about" = [ "firefox.desktop" ]; + "x-scheme-handler/unknown" = [ "firefox.desktop" ]; + "image/png" = "imv.desktop"; + "image/gif" = "imv.desktop"; }; }; }; - - - gtk = { - enable = true; - theme = { - name = "Adwaita-Dark"; - package = pkgs.gnome.gnome-themes-extra; - }; - gtk3.extraConfig = { - Settings = '' - gtk-application-prefer-dark-theme=1 - ''; - }; - - gtk4.extraConfig = { - Settings = '' - gtk-application-prefer-dark-theme=1 - ''; - }; - }; - - home.sessionVariables.GTK_THEME = "Adwaita-Dark"; - - xdg.configFile = { - "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets"; - "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css"; - "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css"; - }; - - dconf = { - enable = true; - settings = { - "org/gnome/desktop/interface" = { - color-scheme = "prefer-dark"; - gtk-theme = "Adwaita-Dark"; - }; - }; - }; - # Wayland, X, etc. support for session vars # systemd.user.sessionVariables = home.sessionVariables; - qt = { - platformTheme = "gtk"; - }; - - - - home.file.".ssh/config".text = '' - HOST nxace - HostName nx2.site - User nx2 - Port 50022 - - HOST nxacel - HostName 192.168.178.32 - User nx2 - Port 50022 - - HOST nxrpi - HostName nx2.site - User pi - Port 50023 - - HOST nxrpil - HostName 192.168.178.31 - User pi - Port 50023 - ''; - - - - - # Let Home Manager install and manage itself. programs.home-manager.enable = true; } diff --git a/secrets/passwords-and-certificates.nix b/secrets/passwords-and-certificates.nix index 6fc13de..85579b8 100644 Binary files a/secrets/passwords-and-certificates.nix and b/secrets/passwords-and-certificates.nix differ diff --git a/hardware-configuration.nix b/system-modules/hardware-configuration.nix similarity index 100% rename from hardware-configuration.nix rename to system-modules/hardware-configuration.nix diff --git a/system-modules/hsmw.nix b/system-modules/hsmw.nix new file mode 100644 index 0000000..a61ae5e --- /dev/null +++ b/system-modules/hsmw.nix @@ -0,0 +1,28 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + environment.systemPackages = [ + pkgs.strongswan + ]; + + environment.etc = { + + # easyroam HSMW + "ssl/certs/easyroam_client_cert.pem".source = ../secrets/easyroam-hsmw/easyroam_client_cert.pem; + "ssl/certs/easyroam_root_ca.pem".source = ../secrets/easyroam-hsmw/easyroam_root_ca.pem; + "ssl/certs/easyroam_client_key.pem".source = ../secrets/easyroam-hsmw/easyroam_client_key.pem; + + + # VPN + "NetworkManager/system-connections/eduroam.nmconnection" = { + text = secrets.easyroamHSMW.nmconfig; + mode = "0600"; + }; + + + }; + + +} + + diff --git a/system-modules/ollama.nix b/system-modules/ollama.nix new file mode 100644 index 0000000..7ba191c --- /dev/null +++ b/system-modules/ollama.nix @@ -0,0 +1,39 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + environment.systemPackages = with pkgs; [ + ollama + ]; + + + systemd.services.ollama = { + description = "Ollama Service"; + after = [ "network-online.target" "ollama-doesnt-respect-xdg-data-home.service" ]; + serviceConfig = { + Type = "simple"; + # Environment = "\"XDG_DATA_HOME=/run/current-system/sw/share\""; + ExecStart = "${pkgs.ollama}/bin/ollama serve"; + User = "ollama"; + Group = "ollama"; + Restart = "always"; + RestartSec = "3"; + }; + wantedBy = [ "default.target" ]; + }; + + users.users.ollama = { + isSystemUser = true; + home = "/usr/share/ollama"; + shell = "/bin/false"; + group = "ollama"; + }; + users.groups.ollama = {}; + + systemd.services.ollama-doesnt-respect-xdg-data-home = { + wantedBy = ["multi-user.target"]; + script = '' + mkdir -p /usr/share/ollama/.ollama + chown ollama:ollama -R /usr/share/ollama + ''; + }; +} \ No newline at end of file diff --git a/system-modules/sound.nix b/system-modules/sound.nix new file mode 100644 index 0000000..5c88876 --- /dev/null +++ b/system-modules/sound.nix @@ -0,0 +1,12 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # If you want to use JACK applications, uncomment this + jack.enable = true; + }; +} \ No newline at end of file diff --git a/system-modules/users.nix b/system-modules/users.nix new file mode 100644 index 0000000..10b7998 --- /dev/null +++ b/system-modules/users.nix @@ -0,0 +1,24 @@ +{ config, pkgs, lib, system, user, allowed, secrets, ... }: + +{ + users.defaultUserShell = pkgs.bash; # if interactive, itll switch to fish + + users.users.nx2 = { + isNormalUser = true; + extraGroups = [ "networkmanager" "wheel" "audio" "video" "docker" "libvirtd" "uinput" ]; + useDefaultShell = true; + packages = with pkgs; []; # all in home.nix + }; + + programs = { + bash = { + interactiveShellInit = '' + if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]] + then + shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION="" + exec ${pkgs.fish}/bin/fish $LOGIN_OPTION + fi + ''; + }; + }; +} \ No newline at end of file