diff --git a/flake.lock b/flake.lock index 9c183ed..309895f 100644 --- a/flake.lock +++ b/flake.lock @@ -159,11 +159,11 @@ }, "locked": { "dir": "contrib", - "lastModified": 1673321445, - "narHash": "sha256-5jdmIgcN2PNWHozyj8WRoSVJBiQi61SqWGfTJXUBDOI=", + "lastModified": 1673504032, + "narHash": "sha256-x4nv7g8+bQXg5PfkFw3vCcr3pYI0Hco0VoSbAy60xek=", "owner": "neovim", "repo": "neovim", - "rev": "1df2db0bc4dfa2e4f632f9b3dbae00b8b29f2d9f", + "rev": "143d3f1f3224bca02bfef7df0932b9d7524a3ff2", "type": "github" }, "original": { @@ -180,11 +180,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1673338492, - "narHash": "sha256-UbqugOENjdtTWCvJQQ0ym80zTB28esvJQPO3j3+Zmjw=", + "lastModified": 1673511313, + "narHash": "sha256-QGUT3w1bHclVRqX958EPOd3OxR/R10MoV97N5jx/qbw=", "owner": "nix-community", "repo": "neovim-nightly-overlay", - "rev": "de5bef64b8158b85b47256d5a366973534130621", + "rev": "5af6fe31f9906e70a1e8985dbbdcc4ae66c7f82d", "type": "github" }, "original": { @@ -211,11 +211,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1673301451, - "narHash": "sha256-0IvOqAXZ+dHjOV7dQl4iEcCUmzqg8VvGg+UZ68ONDIg=", + "lastModified": 1673466167, + "narHash": "sha256-1HzUCtWwHRGzTOHCIKGG0lVL6wvsyPSSyBuIqZWYowc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "35f1f865c03671a4f75a6996000f03ac3dc3e472", + "rev": "68e03abb2fd8db50eaee69ad58b208451143e005", "type": "github" }, "original": { @@ -242,11 +242,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1673226411, - "narHash": "sha256-b6cGb5Ln7Zy80YO66+cbTyGdjZKtkoqB/iIIhDX9gRA=", + "lastModified": 1673450908, + "narHash": "sha256-b8em+kwrNtnB7gR8SyVf6WuTyQ+6tHS6dzt9D9wgKF0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "aa1d74709f5dac623adb4d48fdfb27cc2c92a4d4", + "rev": "6c8644fc37b6e141cbfa6c7dc8d98846c4ff0c2e", "type": "github" }, "original": { @@ -290,11 +290,11 @@ "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1673317790, - "narHash": "sha256-GWjj/bqTXPsKgwWGFZUyHRShxFvufShYnuyyeP99wmk=", + "lastModified": 1673490397, + "narHash": "sha256-VCSmIYJy/ZzTvEGjdfITmTYfybXBgZpMjyjDndbou+8=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "9724998ea2caf23214674bf0c2cdf6ec0b1719af", + "rev": "0833f4d063a2bb75aa31680f703ba594a384ffe6", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 67761b4..ae13cbe 100644 --- a/flake.nix +++ b/flake.nix @@ -25,78 +25,103 @@ neovim-nightly-overlay.url = "github:nix-community/neovim-nightly-overlay"; }; - outputs = { - nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat, - neovim-nightly-overlay - ,... - }@_inputs: let - # Context/global stuffs to be passed down - # TODO: adapt to different platforms think about different systems later - system = "x86_64-linux"; - pkgs = import nixpkgs { - inherit system; - overlays = import ./overlays.nix _inputs; - config = { - allowUnfree = true; - }; - }; - - # inject nixpkgs.lib onto c_ (calculus) - _lib = pkgs.lib; - inputs = (_lib.recursiveUpdate { - inherit system; + outputs = + { nixpkgs + , agenix + , home-manager + , flake-utils + , nixgl + , rust-overlay + , flake-compat + , neovim-nightly-overlay + , ... + }@_inputs: + let + # Context/global stuffs to be passed down # NOTE: this will only read files that are within git tree # all secrets should go into secrets.nix and secrets/*.age - proj_root = let - path = builtins.toString ./.; - in { - inherit path; - configs.path = "${path}/native-configs"; - scripts.path = "${path}/scripts"; - secrets.path = "${path}/secrets"; - testdata.path = "${path}/tests"; - modules.path = "${path}/modules"; - hosts.path = "${path}/hosts"; - users.path = "${path}/users"; - }; - } _inputs); - inputs_w_pkgs = (_lib.recursiveUpdate {inherit pkgs; lib = pkgs.lib;} inputs); - lib = _lib.recursiveUpdate (import ./lib inputs_w_pkgs) _lib; - - # update inputs with our library and past onto our end configurations - inputs_w_lib = (lib.recursiveUpdate {inherit lib;} inputs_w_pkgs); - modules = (import ./modules inputs_w_lib); - hosts = (import ./hosts inputs_w_lib); - users = (import ./users inputs_w_lib); - - # {nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat - # ,pkgs, lib (extended), proj_root} - final_inputs = inputs_w_lib; - - # Tests: unit + integration - unit_tests = (import ./lib/test.nix final_inputs) // - { - test_example = { - expr = "names must start with 'test'"; - expected = "or won't show up"; + proj_root = + let + path = builtins.toString ./.; + in + { + inherit path; + configs.path = "${path}/native_configs"; + scripts.path = "${path}/scripts"; + secrets.path = "${path}/secrets"; + testdata.path = "${path}/tests"; + modules.path = "${path}/modules"; + hosts.path = "${path}/hosts"; + users.path = "${path}/users"; }; - not_show = { - expr = "this will be ignored by lib.runTests"; - expected = "for sure"; + # TODO: adapt to different platforms think about different systems later + system = "x86_64-linux"; + overlays = [ + rust-overlay.overlays.default + (self: pkgs@{ lib, ... }: { + lib = pkgs.lib // (import ./lib (_inputs // { inherit pkgs proj_root; })); + }) + ]; + pkgs = import nixpkgs { + inherit system; + overlays = import ./overlays.nix _inputs; + config = { + allowUnfree = true; + }; + }; + # now, this lib is extremely powerful as it also engulfs nixpkgs.lib + # lib = nixpkgs.lib // pkgs.lib; + lib = (builtins.foldl' (lhs: rhs: (nixpkgs.lib.recursiveUpdate lhs rhs)) { } [ + nixpkgs.lib + pkgs.lib + (import ./lib { + inherit proj_root pkgs overlays system; + inherit (pkgs) lib; + }) + ]); + inputs_w_lib = (pkgs.lib.recursiveUpdate _inputs { + inherit system proj_root pkgs lib; + }); + + modules = (import ./modules inputs_w_lib); + hosts = (import ./hosts inputs_w_lib); + users = (import ./users inputs_w_lib); + + # {nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat + # ,pkgs, lib (extended), proj_root} + final_inputs = inputs_w_lib; + + # Tests: unit + integration + unit_tests = (import ./lib/test.nix final_inputs) // + { + test_example = { + expr = "names must start with 'test'"; + expected = "or won't show up"; + }; + not_show = { + expr = "this will be ignored by lib.runTests"; + expected = "for sure"; + }; + }; + secrets = import ./secrets final_inputs; + + in + { + inherit (hosts) nixosConfigurations; + inherit (users) homeConfigurations; + inherit lib proj_root; + devShell."${system}" = import ./dev-shell.nix final_inputs; + templates = import ./templates final_inputs; + secrets = { + pubKeys = { + hosts = hosts.pubKeys; + users = users.pubKeys; }; }; - in { - inherit (hosts) nixosConfigurations; - # inherit (users) homeConfigurations; - inherit lib; - devShell."${system}" = import ./dev-shell.nix final_inputs; - templates = import ./templates final_inputs; - - unit_tests = lib.runTests unit_tests; - secrets = import ./secrets final_inputs; - debug = { - inherit final_inputs hosts users modules lib inputs_w_lib unit_tests pkgs; + unit_tests = lib.runTests unit_tests; + debug = { + inherit final_inputs hosts users modules lib inputs_w_lib unit_tests pkgs nixpkgs; + }; }; - }; } diff --git a/hosts/bao/hardware-configuration.nix b/hosts/bao/hardware-configuration.nix index c29572c..2851c4f 100644 --- a/hosts/bao/hardware-configuration.nix +++ b/hosts/bao/hardware-configuration.nix @@ -8,6 +8,7 @@ [ (modulesPath + "/installer/scan/not-detected.nix") ]; + boot.loader.systemd-boot.enable = true; boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; # boot.initrd.kernelModules = [ "amdgpu" ]; boot.initrd.kernelModules = []; diff --git a/hosts/default.nix b/hosts/default.nix index cb737de..adea74f 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -10,11 +10,13 @@ config = { system = "x86_64-linux"; preset = "base"; }; + # TODO: add override so that we can add wsl config on top bao.nixosConfig = { modules = [ - import ../modules/kde.sys.nix - import ../modules/pulseaudio.sys.nix - import ../modules/storage.perso.sys.nix + (import ../modules/nvgpu.sys.nix) + (import ../modules/kde.sys.nix) + (import ../modules/pulseaudio.sys.nix) + (import ../modules/storage.perso.sys.nix) ]; }; }; @@ -29,36 +31,45 @@ propagate = hostConfig@{metadata, nixosConfig}: let preset = lib.attrByPath ["preset"] "base" metadata; # infer hardwareConfig = import "${proj_root.hosts.path}/${hostName}/hardware-configuration.nix"; + # alias to prevent infinite recursion + _nixosConfig = nixosConfig; in { inherit hostName ssh_pubkey users nixosVersion system preset hardwareConfig; - nixosConfig = nixosConfig // { + nixosConfig = _nixosConfig // { inherit system; - lib = finalInputs.lib; modules = [ + { + config._module.args = { + inherit proj_root; + my-lib = finalInputs.lib; + }; + } + hardwareConfig { system.stateVersion = nixosVersion; networking.hostName = hostName; users.users = users; } { - _module.args = finalInputs; + imports = [agenix.nixosModule]; + environment.systemPackages = [agenix.defaultPackage.x86_64-linux]; } - import "${proj_root.modules.path}/secrets.nix" - import "${proj_root.modules.path}/${preset}.sys.nix" - ] ++ nixosConfig.modules; + (import "${proj_root.modules.path}/secrets.nix") + (import "${proj_root.modules.path}/${preset}.sys.nix") + ] ++ _nixosConfig.modules; }; }; +# we are blessed by the fact that we engulfed nixpkgs.lib.* at top level mkHostFromPropagated = propagatedHostConfig@{nixosConfig,...}: nixpkgs.lib.nixosSystem nixosConfig; +<<<<<<< HEAD mkHost = hostConfig: (lib.pipe [propagate mkHostFromPropagated] hostConfig); trimNull = lib.filterAttrsRecursive (name: value: value != null); flattenPubkey = lib.mapAttrs (hostName: meta_config: meta_config.metadata.ssh_pubkey); +======= +mkHost = hostConfig: (lib.pipe hostConfig [propagate mkHostFromPropagated]); +>>>>>>> 4619ea4 (rekey) in { - inherit config; - # nixosConfigurations = lib.mapAttrs (name: hostConfig: mkHost hostConfig) config; - nixosConfigurations = {}; - debug = { - propagated = lib.mapAttrs (name: hostConfig: propagate hostConfig) config; - }; + nixosConfigurations = lib.mapAttrs (name: hostConfig: mkHost hostConfig) config; # {bao = "ssh-ed25519 ..."; another_host = "ssh-rsa ...";} - hostKeys = trimNull (flattenPubkey config); + pubKeys = lib.getPubkey config; } diff --git a/lib/default.nix b/lib/default.nix index baf6243..37fcefb 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,22 +1,30 @@ {pkgs -,nixpkgs +# ,nixpkgs ,proj_root -,agenix +# ,agenix ,nixosDefaultVersion? "22.05" ,defaultSystem? "x86_64-linux" ,...}@inputs: let lib = pkgs.lib; - serde = import ./serde.nix inputs // {inherit lib;}; + inputs_w_lib = (inputs // {inherit lib;}); + serde = import ./serde.nix inputs_w_lib; + shellAsDrv = {script, pname}: (pkgs.callPackage ( + # just a pattern that we must remember: args to this are children of pkgs. + {writeShellScriptBin}: writeShellScriptBin pname script + ) {}); + trimNull = lib.filterAttrs (name: value: value != null); + # ssh + flattenPubkey = lib.mapAttrs (_identity: meta_config: lib.attrByPath ["metadata" "ssh_pubkey"] null meta_config); + getPubkey = config: (lib.pipe config [flattenPubkey trimNull]); # procedure = in { # short-hand to create a shell derivation # NOTE: this is pure. This means, env vars from devShells might not # be accessible unless MAYBE they are `export`ed - shellAsDrv = {script, pname}: (pkgs.callPackage ( - # just a pattern that we must remember: args to this are children of pkgs. - {writeShellScriptBin}: writeShellScriptBin pname script - ) {}); - + inherit shellAsDrv trimNull flattenPubkey getPubkey; + ssh = { + inherit flattenPubkey getPubkey; + }; # Configures hosts as nixosConfiguration # mkHost = {hostName # , nixosBareConfiguration diff --git a/modules/amdgpu.sys.nix b/modules/amdgpu.sys.nix new file mode 100644 index 0000000..43ae3f7 --- /dev/null +++ b/modules/amdgpu.sys.nix @@ -0,0 +1,6 @@ +{ + imports = [./gpu.sys.nix]; + boot.initrd.kernelModules = [ "amdgpu" ]; + services.xserver.enable = true; + services.xserver.videoDrivers = [ "amdgpu" ]; +} diff --git a/modules/base.sys.nix b/modules/base.sys.nix index 6c4e836..e2e043d 100644 --- a/modules/base.sys.nix +++ b/modules/base.sys.nix @@ -1,6 +1,7 @@ {pkgs ,lib ,proj_root +,... }:{ imports = [ ./minimal.sys.nix diff --git a/modules/gpu.sys.nix b/modules/gpu.sys.nix new file mode 100644 index 0000000..40a94e5 --- /dev/null +++ b/modules/gpu.sys.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: { + environment.systemPackages = [ pkgs.clinfo pkgs.lshw pkgs.glxinfo pkgs.pciutils pkgs.vulkan-tools ]; + hardware.opengl = { + enable = true; + extraPackages = [ pkgs.rocm-opencl-icd pkgs.rocm-opencl-runtime ]; + # Vulkan + driSupport = true; + driSupport32Bit = true; + package = pkgs.mesa.drivers; + package32 = pkgs.pkgsi686Linux.mesa.drivers; + }; +} diff --git a/modules/kde.sys.nix b/modules/kde.sys.nix index 6744c8e..fc0b862 100644 --- a/modules/kde.sys.nix +++ b/modules/kde.sys.nix @@ -1,7 +1,8 @@ { pkgs -, lib +, my-lib +,... }: { - environment.noXlibs = lib.mkForce false; + environment.noXlibs = my-lib.mkForce false; # TODO: wireless networking # Enable the X11 windowing system. diff --git a/modules/minimal.sys.nix b/modules/minimal.sys.nix index 2af79c1..bd5a729 100644 --- a/modules/minimal.sys.nix +++ b/modules/minimal.sys.nix @@ -1,12 +1,15 @@ {pkgs ,lib ,proj_root +,modulesPath +,... }:{ + imports = ["${modulesPath}/profiles/minimal.nix"]; # prune old builds after a while - nix.settings.auto-optimize-store = true; + nix.settings.auto-optimise-store = true; nix.package = pkgs.nixFlakes; # nix flakes nix.extraOptions = '' - experimental=feature = nix-command flakes + experimental-features = nix-command flakes ''; programs.neovim = { enable = true; @@ -22,6 +25,6 @@ ]; users.users.root = { # openssh runs in root, no? This is because port < 1024 requires root. - openssh.authorizedKeys.keys = lib.strings.splitString "\n" (builtins.readFile "${proj_root}/ssh/authorized_keys"); + openssh.authorizedKeys.keys = lib.strings.splitString "\n" (builtins.readFile "${proj_root.configs.path}/ssh/authorized_keys"); }; } diff --git a/modules/mosh.sys.nix b/modules/mosh.sys.nix index 0e287cf..975f356 100644 --- a/modules/mosh.sys.nix +++ b/modules/mosh.sys.nix @@ -1,6 +1,7 @@ {pkgs ,lib ,config +,... }: { environment.systemPackages = [pkgs.mosh]; networking.firewall = lib.mkIf config.networking.firewall.enable { diff --git a/modules/nvgpu.sys.nix b/modules/nvgpu.sys.nix new file mode 100644 index 0000000..e637694 --- /dev/null +++ b/modules/nvgpu.sys.nix @@ -0,0 +1,7 @@ +{config,...}: { + imports = [./gpu.sys.nix]; + nixpkgs.config.allowUnfree = true; + services.xserver.enable = true; + services.xserver.videoDrivers = [ "nvidia" ]; + hardware.nvidia.package = config.boot.kernelPackages.nvidiaPackages.stable; +} diff --git a/modules/secrets.nix b/modules/secrets.nix index 9c91dc6..cae2025 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -1,8 +1,5 @@ -{agenix -,proj_root}: { - imports = [ - agenix.nixosModule - ]; +{proj_root +,...}: { age.secrets.s3fs = { file = "${proj_root.secrets.path}/s3fs.age"; # mode = "600"; # owner + group only @@ -15,5 +12,8 @@ age.secrets._nhitrl_cred = { file = "${proj_root.secrets.path}/_nhitrl.age"; }; - environment.systemPackages = [agenix.defaultPackage.x86_64-linux]; + age.secrets."wifi.env" = { + file = "${proj_root.secrets.path}/wifi.env.age"; + }; + # environment.systemPackages = [agenix.defaultPackage.x86_64-linux]; } diff --git a/modules/ssh.sys.nix b/modules/ssh.sys.nix index 1e42a3c..7133f33 100644 --- a/modules/ssh.sys.nix +++ b/modules/ssh.sys.nix @@ -1,6 +1,6 @@ { services.openssh = { enable = true; - permitRootLogin = false; + permitRootLogin = "no"; }; } diff --git a/modules/storage.perso.sys.nix b/modules/storage.perso.sys.nix index e16db18..d30e477 100644 --- a/modules/storage.perso.sys.nix +++ b/modules/storage.perso.sys.nix @@ -1,5 +1,5 @@ # Personal configuration on storage solution -{ pkgs, config, lib }: { +{ pkgs, config, lib,... }: { environment.systemPackages = [ pkgs.s3fs pkgs.cifs-utils diff --git a/modules/wifi.sys.nix b/modules/wifi.sys.nix new file mode 100644 index 0000000..90de687 --- /dev/null +++ b/modules/wifi.sys.nix @@ -0,0 +1,8 @@ +{config,...}: { + networking.wireless.enable = true; + networking.wireless.environmentFile = config.age.secrets."wifi.env"; + networking.wireless.networks = { + "Hoang Sa".psk = "@DESERT_PSK@"; + "Truong Sa".psk = "@DESERT_PSK@"; + }; +} diff --git a/nix-conf/system/flake.nix b/nix-conf/system/flake.nix index ef79335..c3943ad 100644 --- a/nix-conf/system/flake.nix +++ b/nix-conf/system/flake.nix @@ -230,7 +230,7 @@ }; amd_rx470 = { # early amd gpu usage - # boot.initrd.kernelModules = ["amdgpu"]; + boot.initrd.kernelModules = ["amdgpu"]; services.xserver.enable = true; services.xserver.videoDrivers = ["amdgpu"]; }; diff --git a/scripts/config-sysnix.sh b/scripts/config-sysnix.sh index 261aa69..f7de08d 100755 --- a/scripts/config-sysnix.sh +++ b/scripts/config-sysnix.sh @@ -19,10 +19,10 @@ fi SCRIPT_DIR=$(realpath $(dirname $0)) echo "SCRIPT_DIR: ${SCRIPT_DIR}" -SYSNIX_DIR="${SCRIPT_DIR}/../nix-conf/system" +SYSNIX_DIR="${SCRIPT_DIR}/.." # Copy hardware-configuration of existing machine onto our version control -SYSNIX_PROF="${SYSNIX_DIR}/profiles/${HOSTNAME}" +SYSNIX_PROF="${SYSNIX_DIR}/hosts/${HOSTNAME}" HARDWARE_CONF="${SYSNIX_PROF}/hardware-configuration.nix" if [ ! -f "${HARDWARE_CONF}" ]; then mkdir "$SYSNIX_PROF" diff --git a/secrets.nix b/secrets.nix index 549ff67..cb26df4 100644 --- a/secrets.nix +++ b/secrets.nix @@ -1,10 +1,21 @@ -(import - ( - let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in - fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; - sha256 = lock.nodes.flake-compat.locked.narHash; - } - ) - { src = ./.; } -).defaultNix.secrets +let + inherit ((import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } + ).defaultNix) secrets; + inherit (secrets) pubKeys; + inherit (pubKeys) users hosts; + all = users // hosts; + c_ = builtins; +in { + "secrets/s3fs.age".publicKeys = c_.attrValues (all); + "secrets/s3fs.digital-garden.age".publicKeys = c_.attrValues (all); + "secrets/_nhitrl.age".publicKeys = c_.attrValues (all); + "secrets/wifi.env.age".publicKeys = c_.attrValues (all); +} diff --git a/secrets/_nhitrl.age b/secrets/_nhitrl.age index 7b3f4d2..ba859ad 100644 Binary files a/secrets/_nhitrl.age and b/secrets/_nhitrl.age differ diff --git a/secrets/s3fs.age b/secrets/s3fs.age index 89113d0..88ed5a8 100644 --- a/secrets/s3fs.age +++ b/secrets/s3fs.age @@ -1,10 +1,10 @@ age-encryption.org/v1 --> ssh-ed25519 ahbzMg 6pTVLAgOY/JZVWiCFHLo8xQ4/CL6620IMaBRpqI8Wws -CtJeQuy5VzKZhJnIH+/cjlKsAcg0RY2bhHTWVm+hUOY --> ssh-ed25519 glsjZQ we7RCgsnODTJ8rKYhU+9tu0DmLH+98mcQKQ3I2slikM -G81lsFLQR9polxme1K/MU2d8Y01PrTqtzJnVq0EMJF0 --> |-grease B\W,I9z ^Gx;$ Kk7!4,P -0Jl5Lhx7R8YOs9S+hUtQDDpNIqBhC/MM0N7w1MCtwYtkIIIWKfY9jkJ7+Cew2Ee5 -Qb04jnE ---- b7AXWRgK45a/91iwmwt5g+CWOlU/2f4nUDfXlg/bs9A -%;3RmQWhp̖V;׮V[z9al=cLvau7,tUܶh^&ֿWJP6-ң n-=] \ No newline at end of file +-> ssh-ed25519 ahbzMg Lx4TLKDZ2yk3DQsM6nOOI1o+FHu0lNtT2p3PBdao+C4 +RsTScUeLmFrO6v1OOxBbyBCMBMVhsGrtu5W9iMOw8B0 +-> ssh-ed25519 glsjZQ CdLCkzb1dBoG9gYdMisaZBZT+nnzfOX326CWq6cvN1s +UKGCxej9lZnLzsuFJnFOMpyrz7YzJrHcrFuDz8l8RQk +-> U