Compare commits

...

63 Commits

Author SHA1 Message Date
aner e36767b625 azos-core bump: fix over-eager AZOS_AGENT_SHELL_SESSION guard on SessionStart hook 2026-10-13 10:55:53 +03:00
aner 2585a0e9d3 Rename claude backend toggles to the new agent-memory/agent-skills shape
Mirrors the azos-core change: azos.claude.enable now sets
azos.agent-memory.backends.claude.enable and
azos.agent-skills.backends.claude.enable instead of the old
azos.claude-memory.enable/azos.claude-skills.enable. The new agent-shell
memory backend needs no wiring here -- it's bundled directly in
azos-core's editor/emacs module, alongside wherever agent-shell itself
gets installed.
2026-10-13 10:51:22 +03:00
aner ac6c15f931 Set real mail accounts and tie presence check to the yubikey toggle
Mirrors the azos-core change: features/mail/default.nix now just sets
accounts.email.accounts (the three real addresses, with the existing
default_account_params/default_gmail_params convenience merging kept
here since it's personal boilerplate, not mechanism) and
azos.mail.presenceCheckCommand, wired to azos-card-present only when
azos.encryption.yubikey.enable is true.
2026-10-13 10:03:48 +03:00
aner b880a194ba Set real values for genericized git-config/encryption/send-alert/printing
Mirrors the azos-core change: drops the now-fully-migrated
features/{git-config,encryption,printing}, rewrites features/homey-alert
down to just the azos-homey-ntfy-alert overlay package (the ntfy-specific
remote-notification command plugged into azos.send-alert.remoteCommand),
and sets every real personal value (name/email/signing key, GPG key id,
YubiKey/browserpass/gpg-ssh toggles and keygrip/pubkey, printing username)
directly in home-manager/home.nix and nixos/configuration.nix, same place
the other personal values (azos.name, azos.headphones.devices) already
live.
2026-10-13 09:50:44 +03:00
aner 8b633f598c Move hfsprogs into azos-core's desktop suite as a NixOS module
Mirrors the azos-core change -- nixos.desktop already imported in
nixos/configuration.nix, so no new import line needed, just drops the
old homeManager.hfsprogs import.
2026-10-13 09:29:02 +03:00
aner da5df102cd Move audio/binfmt/bluetooth/headphones/chess/kubernetes/virtualization into azos-core suites
Mirrors the azos-core change: removes the now-relocated standalone
features from azos/features, and updates both import lists
(home-manager/home.nix, nixos/configuration.nix) to pull the nixos.desktop
and nixos.dev suite modules instead of the old per-feature ones.
2026-10-13 09:19:31 +03:00
aner 5ec9f2c528 azos-core bump: restore exwm's azos-emacs-desktop dependency 2026-10-13 09:05:25 +03:00
aner 80420198e8 Rename azos-core station suite to desktop; move discord out to azos/features
Mirrors the azos-core change: station is renamed desktop (its apps are
generically useful on any machine, work included), discord moves to its
own standalone azos/features/discord (personal-only, so it lives in the
azos project rather than azos-core), and azos-emacs-station becomes
azos-emacs-desktop in lauretta's emacs config to match.
2026-10-13 08:54:39 +03:00
aner 53976751cd Rename azos-core features/ to suites/; fold claude-memory/claude-skills into base
Bumps the azos-core submodule and updates docs/imports to match: AGENTS.md
now documents the suite-grouping convention (no bare top-level modules),
and claude-memory/claude-skills no longer need their own entries in
home-manager/home.nix since they're folded into the base suite.
2026-10-13 08:42:49 +03:00
aner b3380c6ce4 Bugfix 2026-10-11 23:15:45 +03:00
aner 97fdb926ac Auto-notify on long Bash commands; homey-alert local fallback; nextcloud mount fix
- homey-alert: add a global PreToolUse hook that transparently times every
  Bash command Claude runs and fires a notification once a command crosses
  the configured threshold (default 5 min), without needing the skill to
  be invoked manually. Also makes homey-alert always fire a local
  notify-send alongside the ntfy push, since the ntfy server isn't always
  reachable.
- nextcloud: fix sleep crash-loop under the restricted systemd PATH
  (bin/sleep -> coreutils store path).
- azos-core bump (adds ncdu to the base suite).
2026-10-11 23:14:15 +03:00
aner 04427ddcda Nextcloud sync, also zapzap 2026-10-11 09:22:42 +03:00
aner 0ea6d168fd azos-core bump 2026-10-11 00:23:30 +03:00
aner b6f3eee1b1 pcap mode and auto load hook azos-core bump 2026-10-10 23:53:14 +03:00
aner 1d661943cf Add YubiKey U2F login/sudo auth; disable unused features by default
pam_u2f is set up as a sufficient factor ahead of password for sudo and
login (which greetd/tuigreet substacks), so touching the key logs in
without typing a password while leaving password as fallback.
Fingerprint was investigated too but lauretta's reader is an unsupported
match-on-chip sensor, documented in the feature instead of wired up.

Also flip kubectl, qutebrowser-config, and snx-rs to disabled by default
since they're unused.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-09 14:08:33 +03:00
aner d9fbf95ead Mail facelift 2026-10-09 00:01:24 +03:00
aner 0a3a1746cb New mail notifications 2026-10-08 13:21:32 +03:00
aner f079a39cbc Make elfeed-protocol Nextcloud password fetch retriable
A failed pass/gpg fetch (e.g. YubiKey not plugged in yet) used to pass
process output straight to string-trim, which signals instead of
returning nil on empty output, aborting the sentinel before
elfeed-feeds or elfeed-protocol-enable ran. That left elfeed-feeds nil
for the rest of the session with no visible error beyond a *Messages*
line, and every later elfeed-update silently had nothing to fetch.

Wrap the fetch in azos/elfeed-protocol-init-feeds so a failed attempt
can be retried interactively instead of requiring a full reload of the
elfeed-protocol feature.
2026-10-08 13:14:14 +03:00
aner edd18bafdd Remove unused lieer, add silent periodic mbsync timer; bump azos-core
lieer was declared (programs/services.lieer.enable) but had zero real
footprint — mu4e actually fetches via mbsync (mu4e-get-mail-command is
literally "mbsync -a") and sends via msmtp; lieer never had an auth/sync
state file anywhere. Drop it to stop the config suggesting a sync path
that isn't actually in use.

Add a systemd user timer that runs mbsync every 5 minutes. mbsync's
PassCmd shells out to `pass`, which needs the GPG smartcard; on a blind
timer a missing card would otherwise surface as a pinentry "please
insert card" prompt every run. The wrapper script gates the sync behind
`gpg --card-status`, which only queries the reader without invoking
pinentry either way, so a missing card is now a silent no-op instead of
a nag.

Bump azos-core for EDNC popup notifications.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 13:14:08 +03:00
aner c1cb2490ed Bump azos-core: pre-approve org-roam search_nodes/create_node MCP tools
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-06 10:29:17 +03:00
aner 2f4f4257a3 Fix GPG smartcard pinentry routing to Emacs; bump azos-core
The gpg-agent systemd Environment=INSIDE_EMACS=1 hack never worked:
gpg-agent calls gnupg_unsetenv("INSIDE_EMACS") on itself at startup by
design, expecting the variable per-connection from the client instead.
Move it to home.sessionVariables so git/gpg invocations themselves carry
it and forward it to gpg-agent via "OPTION putenv=...", which is what
actually routes a pinentry request to Emacs instead of failing on
curses with no tty.

Bump azos-core for the project-brain-aligned todo/workplate/work-history
skills and the global org-roam Read/Edit permission rules.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-06 10:26:29 +03:00
aner cdb8e15060 Whoops 2026-10-06 09:41:36 +03:00
aner 3b389a5f2a pinentry fixees, exwm gated 2026-10-06 09:40:41 +03:00
aner b20a67fdc6 Bump azos-core: resolve node paths via search_nodes, not content calls 2026-10-06 09:22:02 +03:00
aner 858f68f9c6 Lazily retry lichess token fetch; demand-load lichess package
gpg-agent may not have a cached passphrase yet when the top-level setq
runs at Emacs startup, so a cold agent makes 'pass' fail silently
(stderr redirected) and leaves lichess-token permanently empty for the
session. Retry the fetch right before each use instead of only once
at startup.
2026-10-06 00:30:30 +03:00
aner 8578e23114 Bump azos-core: org-roam-resync hook, no-Emacs-dependency 2026-10-06 00:30:00 +03:00
aner 98b2f461cd Leetcode and chess overhaul 2026-10-05 11:31:04 +03:00
aner f80ed5863e Yay fixes and stuff 2026-10-05 09:33:01 +03:00
aner 1d9784877b Better chess, cuda maintainers fix, elfeed update 2026-09-29 10:45:24 +03:00
aner e5455f35f9 Bugfix 2026-09-09 10:06:13 +03:00
aner fc41d9aef3 agent-shell-math-render update 2026-09-09 09:35:18 +03:00
aner d6916a3fa3 Maildir shortcuts, maildir fix 2026-09-07 07:04:05 +03:00
aner a9b5cd2847 Bump 2026-09-06 17:26:12 +03:00
aner 177963b64e Fixes! 2026-09-06 14:40:40 +03:00
aner e5cc25eb49 Fixy 2026-09-06 13:54:15 +03:00
aner 8fde1cd5fe FIx 2026-09-06 13:47:09 +03:00
aner 21be2b0c87 Version bump 2026-09-06 13:29:20 +03:00
aner e27b7cb777 Fixy fix 2026-09-06 13:24:45 +03:00
aner f4923cbcad Experimental features bump 2026-09-06 11:59:39 +03:00
aner 630054fb8d azos-core bump 2026-09-06 11:57:29 +03:00
aner 9909fb411b Pinentry update 2026-09-06 11:55:47 +03:00
aner 9c64e1513e Remote run skill, mu4e change 2026-09-06 11:49:54 +03:00
aner 943498ce52 Homey alert! 2026-09-03 11:37:12 +03:00
aner df97c76527 Added 8bitdo 2026-08-26 20:25:27 +03:00
aner 8be92183bb Headphone mechanism change 2026-08-20 10:18:57 +03:00
aner 4ea2421734 Beacon updated 2026-07-26 10:51:18 +03:00
aner fa2c62e2f4 azos-core bump 2026-07-26 01:20:47 +03:00
aner a6ff616c2d azos-core version bump 2026-07-26 00:53:03 +03:00
aner 6e0f938e65 New beacon config, redone passwords 2026-07-25 11:45:17 +03:00
aner 59c05832b1 New encryption key 2026-07-25 00:00:39 +03:00
aner b8eb351e6c Interim fix, no gpg key 2026-07-15 20:47:04 +03:00
aner 78afc9e5bf azos-core bump 2026-06-18 22:26:02 +03:00
aner ebdee10fba Bump azos-core, configuration limit. 2026-06-18 21:05:46 +03:00
aner 890f39079b Updated skills and lock and lichess 2026-06-17 07:36:21 +03:00
aner e0a5891cd8 Bump azos-core 2026-06-08 22:01:51 +03:00
aner 7f27339312 Bump azos-core: org-roam-mcp direct SQLite writes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:55:40 +03:00
aner bd64633454 Bump azos-core: org-roam-mcp fork with db-sync fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:47:49 +03:00
aner 7c187d1c3d Updated azos-core and org roam stuff. 2026-06-07 08:01:40 +03:00
aner 1adc0439ea Updated roam backup 2026-06-07 01:27:09 +03:00
aner 2254fd419d Claude as preffered agent, azos-core bump. 2026-06-07 01:18:12 +03:00
aner cf976ae14a Claude memory, second brain, skills 2026-06-07 00:48:20 +03:00
aner c928f5f748 Update lock, more azos-core 2026-06-03 23:49:41 +03:00
aner 8d0f541fbe WTTR 2026-06-02 10:49:52 +03:00
44 changed files with 932 additions and 368 deletions
+140 -54
View File
@@ -22,7 +22,7 @@ nix build .#formatter.x86_64-linux
### Deploying
```bash
# Rebuild the azos environment for lauretta (this machine) — use this when asked to "rebuild"
sudo nixos-rebuild switch --flake '.?submodules=1#lauretta'
azos-lauretta-update
nix flake update --flake '.?submodules=1' # Update all inputs
nix flake lock --flake '.?submodules=1' --update-input X # Update specific input
```
@@ -70,76 +70,119 @@ emacsclient -c -e '(switch-to-buffer (get-buffer-create "test"))'
emacsclient -e '(message "hello")'
```
## Code Style Guidelines
## Repository Structure
### File Organization
- **Home-manager modules**: `modules/home-manager/<name>.nix`
- **NixOS modules**: `modules/nixos/<name>.nix`
- **Imports**: All modules in `modules/home-manager/default.nix` and `modules/nixos/default.nix` (alphabetical order)
- **Home config**: `home-manager/home.nix` - main home-manager user config
- **Custom packages**: `pkgs/` - custom package definitions
- **Overlays**: `overlays/` - package overlays (addpkgs, modifications, unstable-packages)
```
azos/
├── flake.nix # Main flake
├── home-manager/home.nix # Home-manager entry point; manually imports all modules
├── _machines/ # Per-machine NixOS configs (pass suiteModules as specialArgs)
├── nixos/ # NixOS system configs (configuration.nix, configuration-vm.nix, etc.)
├── features/ # Machine-specific home-manager features (auto-discovered)
├── overlays/ # Package overlays
├── shells/ # Dev shells
└── azos-core/ # Shared feature library (git submodule)
├── flake.nix
├── suites/ # Suites, each grouping related sub-features (auto-discovered)
├── overlays/ # Core overlays
└── _lib/ # Module schema helpers
```
Features are auto-discovered by `import-tree` — no central imports file. Each feature's
`default.nix` registers itself via `config.flake.modules.homeManager.<name>`. Modules are
then explicitly imported in `home-manager/home.nix` via `suiteModules.homeManager.<name>`.
**Where to put a new feature:**
- Shared / reusable across machines → inside an existing or new suite directory,
`azos-core/suites/<suite>/<name>/default.nix` (registering
`config.flake.modules.homeManager.<suite>`) — never a bare file directly under
`azos-core/suites/`; every azos-core feature belongs to a suite.
- Machine-specific → `azos/features/<name>/default.nix`
## Code Style Guidelines
### Nix Module Template
All features follow this flake-parts registration pattern:
```nix
{
{...}: {
config.flake.modules.homeManager.<name> = {
lib,
config,
pkgs,
...
}: let
isEnabled =
config.azos.<module-name>.enable;
in {
options.azos.<module-name>.enable = lib.mkOption {
default = true;
}: {
options.azos.<name>.enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
};
config = lib.mkIf isEnabled {
home.packages = with pkgs; [ pkg1 pkg2 ];
config = lib.mkIf config.azos.<name>.enable {
home.packages = with pkgs; [pkg1 pkg2];
};
};
}
```
### Naming Conventions
- Option paths: `config.azos.<module-name>.<option>`
- Enable option: `enable` (bool), default `true`
- Module names: kebab-case (`libreoffice.nix`, `git-config.nix`)
- Option names: may differ from filename (e.g., `git.nix` uses `azos.git-config`)
- Variables: kebab-case (`isEnabled`)
- Option paths: `azos.<module-name>.<option>`
- Module names: kebab-case (`git-config`, `desktop`)
- Feature directories: kebab-case, one `default.nix` per feature
- Variables: kebab-case
### Formatting
- Indentation: 2 spaces
- Let bindings: multi-line with `isEnabled` on its own line
- Packages: Use `with pkgs; [ ... ]` syntax
- Packages: `with pkgs; [pkg1 pkg2]` (no trailing semicolon inside list)
### Imports
- Always include `{...}` for module args
- Standard args: `lib, config, pkgs, ...`
- NixOS config args: `inputs, outputs, lib, config, pkgs, ...`
- Use `./relative/path.nix` for local imports
- Always include `{...}` for the outer module args
- Inner module args: `lib, config, pkgs, ...`
### Option Patterns
- Boolean enable: `lib.mkOption { default = true; example = true; type = lib.types.bool; }`
- Conditional config: `lib.mkIf isEnabled { ... }`
- User-overridable: `lib.mkDefault`
- Boolean enable: `lib.mkOption { default = false; example = true; type = lib.types.bool; }`
- Conditional config: `lib.mkIf config.azos.<name>.enable { ... }`
- Auto-enable a dependency: `azos.<dep>.enable = lib.mkDefault true;`
- Force value: `lib.mkForce` (sparingly)
### Extensible Options
For options that multiple modules should be able to contribute to, use attrset options:
```nix
options.azos.<name>.things = lib.mkOption {
default = {};
type = lib.types.attrsOf lib.types.path; # or lines, str, etc.
};
```
Any module can then add entries without modifying the owning feature. Examples in use:
- `azos.claude.globalSkills` — attrset of skill name → markdown file path
- `azos.claude.globalMdSections` — attrset of key → markdown string (merged into `~/.claude/CLAUDE.md`)
### Home-Manager vs NixOS
- Home-manager: `home.packages`, `home.file`, `programs.<program>`
- NixOS: `config.services`, `environment.systemPackages`
### Deploying Files
- Static file: `home.file."dest".source = ./file;`
- Generated text: `home.file."dest".text = "...";`
- Runtime script (e.g. merging JSON at activation): `home.activation.<name> = lib.hm.dag.entryAfter ["writeBoundary"] ''...'';`
### Suites System
Modules are organized into suites (defined in `azos-core/`):
- `azos.suites.base` - Base packages and config
- `azos.suites.editor` - Editor tools
- `azos.suites.dev` - Development tools
- `azos.suites.station` - Desktop applications
- `azos.suites.exwm` - EXWM window manager
- Enable in `home-manager/home.nix` with `azos.suites.<name>.enable = true;`
Top-level suites group related features (defined in `azos-core/`):
- `azos.suites.base` — base packages and config
- `azos.suites.editor` — editor tools
- `azos.suites.dev` — development tools
- `azos.suites.desktop` — desktop session plumbing (flameshot, dunst, keyboard layout) plus generally-useful apps (browser, libreoffice, zoom, spotify, gimp, whatsapp). Shared, lives in azos-core — wanted on any GUI machine, work included.
- `azos.suites.exwm` — EXWM window manager, depends on `desktop`
Machine-specific, personal-only apps (steam, discord) are **not** part of any azos-core
suite — they live as standalone features directly in `azos/features/`, imported only on
machines that want them (e.g. `azos/features/discord`, `azos/features/steam`), since any
such machine already uses the `azos` project rather than a different downstream repo.
The machine suite (`azos.suites.lauretta`) enables the relevant suites for this machine.
### Specializations
NixOS supports specializations for alternative configurations:
@@ -158,33 +201,76 @@ specialisation = {
## Adding New Modules
1. Create file in `modules/home-manager/` or `modules/nixos/`
2. Add import to `modules/<type>/default.nix` (alphabetical)
3. Use module template above
1. Create `features/<name>/default.nix` (machine-specific) or, for shared features,
`azos-core/suites/<suite>/<name>/default.nix` inside an existing or new suite
(registering `config.flake.modules.homeManager.<suite>`, not a standalone module name)
2. Use the module template above
3. Machine-specific: add `suiteModules.homeManager.<name>` to the imports list in
`home-manager/home.nix`. Shared: no change needed if the suite is already imported.
4. Run `nix fmt`
> **Submodule gotcha**: New files in `azos-core/` must be `git add`-ed inside the submodule
> before `nix build` will see them — Nix flakes only evaluate git-tracked files.
> ```bash
> cd azos-core && git add suites/<suite>/<name>/
> ```
## Agent Memory/Skills Integration
Memory (org-roam) and skills (slash commands/CLAUDE.md) are backend-pluggable, not
Claude-specific, even though Claude is currently the only skills backend and one of two
memory backends:
| Feature | Option | What it does |
|---------|--------|--------------|
| `azos-core/suites/base/agent-memory` | `azos.agent-memory.backends.claude.enable` | Registers org-roam-mcp as a global MCP server in `~/.claude.json`; hooks resync org-roam's index on edit and inject project context at session start |
| `azos-core/suites/base/agent-memory` | `azos.agent-memory.backends.agent-shell.enable` | Registers org-roam-mcp via `agent-shell-mcp-servers` and resyncs on `file-write` events — applies regardless of which ACP backend (Claude, Gemini CLI, Codex, ...) a given agent-shell session runs. Also marks Claude sessions agent-shell launches (`AZOS_AGENT_SHELL_SESSION=1`) so the claude backend's own hooks no-op for those sessions instead of double-acting |
| `azos-core/suites/base/agent-skills` | `azos.agent-skills.backends.claude.enable` | Deploys skills to `~/.claude/commands/` and content to `~/.claude/CLAUDE.md` |
| `azos/features/claude` | `azos.claude.enable` | Installs claude-code, auto-enables the claude backend for both of the above |
| `azos-core/suites/editor/emacs` | (bundled, not a separate option) | Installs agent-shell, auto-enables `azos.agent-memory.backends.agent-shell.enable` |
Both agent-memory and agent-skills register `config.flake.modules.homeManager.base`
(they live inside the `base` suite, since that's where agent-shell is introduced) — not
standalone module names, so no separate `suiteModules.homeManager.*` import is needed for
them in `home-manager/home.nix`.
### Adding Claude skills or standing instructions
From any module — no need to touch azos-core:
```nix
azos.claude.globalSkills.my-skill = ./skills/my-skill.md;
azos.claude.globalMdSections.my-rule = ''
# My Rule
Always do X when Y.
'';
```
`globalSkills`/`globalMdSections` stay Claude-specific (`~/.claude/commands/`,
`~/.claude/CLAUDE.md`) deliberately — no other backend has a uniform equivalent yet. See
`azos-core/suites/base/agent-skills/README.md` for full documentation.
## Key Files
| File | Purpose |
|------|---------|
| `flake.nix` | Main flake, defines systems, overlays |
| `modules/home-manager/default.nix` | Home-manager imports |
| `modules/nixos/default.nix` | NixOS imports |
| `home-manager/home.nix` | User home-manager config, enables suites |
| `nixos/configuration.nix` | Lauretta laptop config |
| `flake.nix` | Main flake, defines systems and overlays |
| `home-manager/home.nix` | Home-manager entry point, imports all modules |
| `_machines/lauretta.nix` | Lauretta machine config, passes `suiteModules` as specialArgs |
| `nixos/configuration.nix` | Lauretta NixOS system config |
| `nixos/configuration-vm.nix` | Test VM config |
| `overlays/` | Custom package overlays |
| `pkgs/` | Custom packages |
| `azos-core/` | Shared modules (submodule) |
| `overlays/` | Package overlays |
| `azos-core/` | Shared feature library (git submodule) |
| `azos-core/suites/` | Suites, each grouping related shared sub-features (auto-discovered by import-tree) |
| `features/` | Machine-specific features (auto-discovered by import-tree) |
| `azos-core/suites/editor/emacs/config.org` | Literate Emacs config |
| `azos-core/suites/base/claude-skills/README.md` | Claude skills extensibility docs |
## Common Tasks
**Add system package**: Edit NixOS module, add to `environment.systemPackages = with pkgs; [ pkg ]`
**Add system package**: Edit a NixOS feature, add to `environment.systemPackages = with pkgs; [ pkg ]`
**Add home-manager package**: Edit module, add to `home.packages = with pkgs; [ pkg ]`
**Add home-manager package**: Edit a feature's config block, add to `home.packages = with pkgs; [ pkg ]`
**Add system service**: Edit NixOS module, add under `services.<service>`
**Add system service**: Edit a NixOS feature, add under `services.<service>`
**Add custom package**: Create file in `pkgs/`, add to `pkgs/default.nix`, use via overlay
**Add custom package**: Add to `azos-core/overlays/` via `config.flake.overlayPkgs.<name>`, then use as `pkgs.<name>`
**Access unstable packages**: Use `pkgs.unstable.<package>` (via unstable-packages overlay)
Symlink
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+17
View File
@@ -0,0 +1,17 @@
{
config,
inputs,
...
}: {
config.flake.nixosConfigurations.beacon-wsl = inputs.nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs;
outputs = config.flake;
suiteModules = config.flake.modules;
};
modules = [../nixos/configuration-beacon-wsl.nix];
};
config.flake.packages.x86_64-linux.beacon-wsl-tarball =
config.flake.nixosConfigurations.beacon-wsl.config.system.build.tarballBuilder;
}
-41
View File
@@ -1,41 +0,0 @@
{...}: {
config.flake.modules.homeManager.audio = {
lib,
config,
...
}: {
options.azos.home-audio.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.home-audio.enable {};
};
config.flake.modules.nixos.audio = {
lib,
config,
pkgs,
...
}: {
options.azos.hardware-audio.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.hardware-audio.enable {
services = {
pipewire = {
enable = true;
audio.enable = true;
pulse.enable = true;
alsa = {
enable = true;
support32Bit = true;
};
jack.enable = true;
};
};
environment.systemPackages = with pkgs; [pavucontrol];
musnix.enable = true;
};
};
}
-15
View File
@@ -1,15 +0,0 @@
{...}: {
config.flake.modules.nixos.binfmt = {
lib,
config,
...
}: {
options.azos.binfmt.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.binfmt.enable {
boot.binfmt.emulatedSystems = ["aarch64-linux"];
};
};
}
-16
View File
@@ -1,16 +0,0 @@
{...}: {
config.flake.modules.nixos.bluetooth = {
lib,
config,
...
}: {
options.azos.bluetooth.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.bluetooth.enable {
services.blueman.enable = true;
hardware.bluetooth.enable = true;
};
};
}
+2
View File
@@ -11,6 +11,8 @@
};
config = lib.mkIf config.azos.claude.enable {
home.packages = with pkgs; [claude-code claude-agent-acp];
azos.agent-memory.backends.claude.enable = lib.mkDefault true;
azos.agent-skills.backends.claude.enable = lib.mkDefault true;
};
};
}
+16
View File
@@ -0,0 +1,16 @@
{...}: {
config.flake.modules.homeManager.discord = {
lib,
config,
pkgs,
...
}: {
options.azos.discord.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.discord.enable {
home.packages = with pkgs; [discord];
};
};
}
-37
View File
@@ -1,37 +0,0 @@
{...}: {
config.flake.modules.homeManager.encryption = {
lib,
config,
pkgs,
...
}: {
options.azos.encryption.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.encryption.enable {
programs.password-store = {
enable = true;
settings = {
PASSWORD_STORE_KEY = "076AA297579A0064";
};
};
home.packages = with pkgs; [
yubikey-personalization
pinentry-gtk2
];
programs.gpg = {
enable = true;
};
services.gpg-agent = {
enable = true;
enableSshSupport = true;
grabKeyboardAndMouse = false;
pinentry.package = pkgs.pinentry-gtk2;
};
home.file.".ssh/config".source = ./ssh-config;
home.file.".ssh/gpg-as-ssh.pub".source = ./gpg-as-ssh.pub;
home.file.".gnupg/sshcontrol".source = ./sshcontrol;
};
};
}
-1
View File
@@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBFZRqiTsOCAJPMqUyMeLd2MbyjdGoyqDVq5/Inhb6EOaM1NUGG4b6FPmYgFLyJIm5LC9BOo6M7npiaiOs/zMqp+hoGLNQUNwm5/G0uy1bjkEfKdUTdGnJ2+M9rkxrR1c+KXrjkiqECqTbnPE4mJbGyVxBW2MwMeP5w8c0DB5KO528PetvHMPPQuEdXyZzDI4kKtVpMlJoPIrIGlNFX0G/wrgXcM4zU1snOTuYGqZnWW++4kBsgIlRKpf/bLJyUMTp30eLVr0fQ6OMBtj1tzUUBaaowU6VGYQQDU/rIh/NpkA2cEVPXZegM4OohkAqrJBFPIAg90WD9Z/SyQlz0Jn8PpAloP0Cuq2vVRr+QLEwxqGiFq91YQ2VtwksMHwJGVrXRCNegpxTZQijWMEd+o0FD2cEd7Ftw6v2L6g12GJ3QGX/q0d/u0GongLLa9fPXl4VoAu7AL+cUcbX/SS7RCG8kYAR3DwOazVbK0NWEdwvWdoSU4lZ3j2at1xqMGjHjyLiTeUqZBjm+Sl5MJWIYNg+8hnONljvggg4SzDFDAkgVLZtOCaZibsMA1ucGR7VRCM09uoaEI4/ZS5pCBtYcp8X67Bv67Og8s2NFf5sUfYBPPKpdBSs+dEPycNVff6JlmzfNiyzLawacGKIDWYSgkOl43N/5ehtpsL3HMZ+5SVNIw== (none)
-1
View File
@@ -1 +0,0 @@
IdentityAgent ${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh
-1
View File
@@ -1 +0,0 @@
61D809B46CEE2A0AF799C4C2FADB0F61A19EEABD
-32
View File
@@ -1,32 +0,0 @@
{...}: {
config.flake.modules.homeManager.git-config = {
lib,
config,
pkgs,
...
}: {
options.azos.git-config.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.git-config.enable {
home.packages = with pkgs; [pass-git-helper unzip];
programs.git = {
enable = true;
signing = {
key = "6D17E295C70E2674";
signByDefault = true;
};
settings = {
credential.helper = "!pass-git-helper $@";
user = {
name = "Aner Zakobar";
email = "aner@zakobar.com";
};
};
};
home.file.".config/pass-git-helper/git-pass-mapping.ini".source =
./pass-git-mapping.ini;
};
};
}
-2
View File
@@ -1,2 +0,0 @@
[*git.zakobar.com*]
target=zakobar.com/users/aner
+52
View File
@@ -0,0 +1,52 @@
{...}: {
config.flake.modules.nixos.hardware-auth = {
lib,
config,
pkgs,
...
}: {
options.azos.hardware-auth.enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
description = ''
Enables YubiKey (U2F/FIDO2) as a "sufficient" PAM factor ahead of
the password, for both sudo and login (which greetd/tuigreet
substacks) -- touch the key to auth, or just type your password as
normal if it's not plugged in.
After enabling and rebuilding, enroll each key on the new machine
(per-user, not machine-wide state, so this must be redone per
machine):
mkdir -p ~/.config/Yubico
pamu2fcfg > ~/.config/Yubico/u2f_keys
To add a second/backup key without overwriting the first:
pamu2fcfg -n >> ~/.config/Yubico/u2f_keys
Test with `sudo true` (touching the key) before trusting it on the
greeter -- a login lockout is harder to recover from than a failed
sudo in an already-open session.
'';
};
config = lib.mkIf config.azos.hardware-auth.enable {
# Default NixOS PAM rule ordering already tries u2f before pam_unix
# (password), both "sufficient" -- so YubiKey touch wins first,
# password always remains as fallback.
#
# Fingerprint (fprintd) is deliberately not wired up here: lauretta's
# reader is a Synaptics Metallica MIS (06cb:009a), a match-on-chip
# sensor unsupported by upstream libfprint. The only known fix is an
# unofficial python-validity + open-fprintd stack, not packaged in
# nixpkgs and fragile enough (suspend/resume, PAM lockout risk) to not
# be worth it for now.
security.pam.u2f = {
enable = true;
settings.cue = true;
};
};
};
}
-20
View File
@@ -1,20 +0,0 @@
{...}: {
config.flake.modules.homeManager.headphones = {
lib,
config,
pkgs,
...
}: {
options.azos.headphones-whmx4000.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.headphones-whmx4000.enable {
home.packages = [
(pkgs.writeShellScriptBin
"azos-connect-headphones-whmx4000"
"echo \"connect AC:80:0A:AF:E1:C2\" | bluetoothctl")
];
};
};
}
-16
View File
@@ -1,16 +0,0 @@
{...}: {
config.flake.modules.homeManager.hfsprogs = {
lib,
config,
pkgs,
...
}: {
options.azos.hfsprogs.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.hfsprogs.enable {
home.packages = with pkgs; [hfsprogs];
};
};
}
+28
View File
@@ -0,0 +1,28 @@
{...}: {
config.flake.overlayPkgs.azos-homey-ntfy-alert = pkgs:
pkgs.writeShellApplication {
name = "azos-homey-ntfy-alert";
runtimeInputs = with pkgs; [curl pass];
text = ''
TOKEN="$(pass zakobar-homecenter/ntfy-token)"
CMD=(
curl -sf
-H "Authorization: Bearer $TOKEN"
-H "Priority: ''${PRIORITY:-default}"
)
[[ -n "''${TITLE:-}" ]] && CMD+=(-H "Title: $TITLE")
[[ -n "''${TAGS:-}" ]] && CMD+=(-H "Tags: $TAGS")
CMD+=(-d "''${MESSAGE:-}" https://ntfy.zakobar.com/alerts)
if [[ -n "''${AZOS_SEND_ALERT_PRINT_REMOTE:-}" ]]; then
# Shell-quote each element so the output is safe to embed in SSH commands --
# the token is already resolved above, so the remote host only needs curl.
printf '%q ' "''${CMD[@]}"
printf '\n'
else
"''${CMD[@]}"
fi
'';
};
}
-16
View File
@@ -1,16 +0,0 @@
{...}: {
config.flake.modules.homeManager.kubernetes = {
lib,
config,
pkgs,
...
}: {
options.azos.kubectl.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.kubectl.enable {
home.packages = with pkgs; [kubectl kubernetes-helm velero];
};
};
}
+3 -1
View File
@@ -12,9 +12,11 @@ orgTrivialBuild {
pkgs.azos-emacs-dev
pkgs.azos-emacs-editor
pkgs.azos-emacs-exwm
pkgs.azos-emacs-station
pkgs.azos-emacs-desktop
agent-shell
elfeed-protocol
org-caldav
pinentry
];
}
+239 -7
View File
@@ -9,11 +9,17 @@
(require 'azos-emacs-dev)
(require 'azos-emacs-editor)
(require 'azos-emacs-exwm)
(require 'azos-emacs-station)
(require 'azos-emacs-desktop)
#+end_src
* Lauretta specific
** Weather
#+begin_src emacs-lisp
(setq wttrin-default-cities '("Meitar, Israel"))
#+end_src
** LLM
#+begin_src emacs-lisp
@@ -28,19 +34,46 @@
:models '(openai/gpt-oss-120b)))
#+end_src
** GPG Pinentry
gpg-agent is configured with =pinentry.package = pkgs.pinentry-emacs=, which
needs a running Emacs-side pinentry service to hand it prompts over a
loopback socket. Without =pinentry-start=, the pinentry-emacs binary can't
reach Emacs and falls back to the curses pinentry (visible as a TUI prompt
when committing from vterm) or hangs entirely (as seen from Magit).
#+begin_src emacs-lisp
(require 'pinentry)
(pinentry-start)
#+end_src
** Agent Shell
#+begin_src emacs-lisp
(setq agent-shell-opencode-default-model-id "opencode/big-pickle")
;; (setq agent-shell-preferred-agent-config (agent-shell-opencode-make-agent-config))
(setq agent-shell-preferred-agent-config 'claude-code)
#+end_src
** Headphones
#+begin_src emacs-lisp
(defun azos/connect-headphones ()
(interactive)
(start-process-shell-command "connect-headphones" nil "azos-connect-headphones-whmx4000"))
(defun azos/connect-headphones (&optional arg)
"Connect to headphones via bluetoothctl.
Without prefix ARG, connects to the first device in the list.
With prefix ARG, prompts to choose from all configured devices."
(interactive "P")
(if (not arg)
(start-process-shell-command "connect-headphones" nil "azos-connect-headphones")
(let* ((raw (shell-command-to-string "azos-connect-headphones --list"))
(lines (split-string (string-trim raw) "\n" t))
(choices (mapcar (lambda (line)
(let ((space (string-match " " line)))
(cons (substring line (1+ space))
(substring line 0 space))))
lines))
(name (completing-read "Connect headphones: " (mapcar #'car choices) nil t))
(mac (cdr (assoc name choices))))
(start-process-shell-command "connect-headphones" nil
(concat "azos-connect-headphones --mac " mac)))))
(define-key azos/global-minor-mode/open-keymap
(kbd "h") 'azos/connect-headphones)
@@ -147,7 +180,7 @@
(interactive)
(let* ((password (string-trim
(shell-command-to-string
(format "pass zakobar.com/users/%s" azos/lauretta/nextcloud-user))))
"pass zakobar.com | head -1")))
(url-http-real-basic-auth-storage
(list (list "nextcloud.zakobar.com:443"
(cons azos/lauretta/nextcloud-user password)))))
@@ -157,6 +190,149 @@
(kbd "C") 'azos/caldav-sync)
#+end_src
** Elfeed Nextcloud News Sync
[[https://github.com/fasheng/elfeed-protocol][elfeed-protocol]] adds an =owncloud+= protocol that speaks the
ownCloud News API, which the Nextcloud News app also implements, so
it syncs elfeed's feed list and read/unread state with the Nextcloud
News app instead of just reading a local feed list one-way.
Reuses the same =zakobar.com= pass entry as the CalDAV sync above,
since it's the same Nextcloud account.
As of elfeed-protocol 1.0.0 (paired with elfeed >= 4.0.0), the
credentials go directly on =elfeed-feeds= — the older
=elfeed-protocol-feeds= variable is dead: setting it only logs a
deprecation warning, and =elfeed-feeds= ends up with the bare URL
and no =:password=, so requests silently authenticate with an empty
password and nothing ever lands in the db.
Fetching the password with =shell-command-to-string= used to
deadlock Emacs whenever the GPG PIN cache had expired: that call
blocks Emacs's single thread on the =pass|gpg= subprocess, but
=pinentry-emacs= (see the GPG Pinentry section above) needs Emacs's
command loop running to answer its loopback prompt — so Emacs waits
on gpg-agent while gpg-agent waits on Emacs. Fetching the password
with =make-process= instead keeps the command loop alive, so
=pinentry-emacs= can prompt normally; =elfeed-feeds= and
=elfeed-protocol-enable= are only set once the process sentinel
fires. Same stderr-redirect reasoning as before, to keep a stray
gpg/pass warning off the captured password.
The fetch is wrapped in a named, interactive function rather than
inlined in =:config= so a failed attempt (e.g. =pass= produced no
output because the YubiKey wasn't plugged in yet) can be retried
with =M-x azos/elfeed-protocol-init-feeds= — re-running =:config=
itself would require reloading the =elfeed-protocol= feature
entirely. An earlier version passed =(process-get proc 'output)=
straight to =string-trim=, which signals (not just returns nil) when
no output was ever read, aborting the sentinel before =elfeed-feeds=
or =elfeed-protocol-enable= ran — so a failed first attempt left
=elfeed-feeds= permanently =nil= for the rest of the session with no
visible error beyond a =*Messages*= line, and every subsequent
=elfeed-update= silently had nothing to fetch.
#+begin_src emacs-lisp
(defun azos/elfeed-protocol-init-feeds ()
"Fetch the Nextcloud password and (re)enable elfeed-protocol sync.
Unlike the one-shot `use-package' :config form this is called from,
safe to call again (e.g. via \\[azos/elfeed-protocol-init-feeds]) if
a previous attempt failed, such as the YubiKey not being plugged in
yet — it re-spawns the `pass' process and re-prompts for the PIN."
(interactive)
(make-process
:name "elfeed-protocol-pass"
:command '("sh" "-c" "pass zakobar.com 2>/dev/null | head -1")
:noquery t
:filter (lambda (proc chunk)
(process-put proc 'output (concat (or (process-get proc 'output) "") chunk)))
:sentinel (lambda (proc _event)
(let ((password (string-trim (or (process-get proc 'output) ""))))
(if (string-empty-p password)
(message "elfeed-protocol: `pass zakobar.com' produced no output; retry with M-x azos/elfeed-protocol-init-feeds")
(setq elfeed-feeds
`(("owncloud+https://aner@nextcloud.zakobar.com"
:password ,password)))
(elfeed-protocol-enable)
(elfeed-update))))))
(use-package elfeed-protocol
:after elfeed
:config
(setq elfeed-protocol-enabled-protocols '(owncloud))
(azos/elfeed-protocol-init-feeds))
#+end_src
** Elfeed Full Article Fetch
Many feeds only publish a short excerpt. elfeed >= 4.0 has built-in
commands for this — =f= (=elfeed-show-fetch-link=) fetches the
linked page and appends it to the show buffer, =R=
(=elfeed-show-readable=) strips the fetched page down to
article text via eww's readability scorer — and both can run
automatically via =elfeed-show-update-hook=, gated on a feed's
=:fetch-link=/=:readable= metadata.
That gating keys off an exact match on the feed's URL/id in
=elfeed-feeds=, which breaks for ownCloud/Nextcloud subfeeds:
elfeed-protocol synthesizes a per-subfeed id of the form
=<host-url>::<subfeed-url>= that never appears in =elfeed-feeds=
(only the bare host URL does), so the metadata lookup always misses
and the stock hooks never fire. Replacing them with unconditional
versions makes full-text + readable-mode the default for every
entry instead.
#+begin_src emacs-lisp
(defun azos/elfeed-show-auto-readable ()
"Like `elfeed-show-auto-readable', but unconditional."
(unless (local-variable-p 'elfeed-transform-html-functions)
(let ((inhibit-message t))
(elfeed-show-readable))))
(defun azos/elfeed-show-auto-fetch-link ()
"Like `elfeed-show-auto-fetch-link', but unconditional."
(elfeed-show-fetch-link))
(setq elfeed-show-update-hook
(list #'azos/elfeed-show-auto-readable #'azos/elfeed-show-auto-fetch-link))
#+end_src
** Lichess
=lichess.org= in pass already holds the website login password, and
lichess.el's =auth-source-pass= lookup resolves by bare hostname, so
the API token can't live under that same entry without colliding.
Store it separately under =lichess.org/token= (=pass insert
lichess.org/token=) and set the =lichess-token= variable directly —
=lichess-token= (the function) checks this variable before falling
back to =auth-source=, so this takes precedence without disturbing
the existing =lichess.org= entry or its consumers (e.g. browserpass).
=shell-command-to-string= merges stderr into its return value, so any
gpg/pass warning on stderr (e.g. an unsafe-permissions notice) would
otherwise get concatenated onto the token and break auth silently.
Redirect stderr away so only the token itself is ever captured.
#+begin_src emacs-lisp
(setq lichess-token
(string-trim (shell-command-to-string "pass lichess.org/token 2>/dev/null | head -1")))
#+end_src
=gpg-agent= may not have a cached passphrase yet when the =setq= above
runs at Emacs startup, in which case =pass= fails silently (stderr is
redirected away) and =lichess-token= is left as =""=. Retry the fetch
lazily right before each actual use, so a cold agent at startup
doesn't permanently wedge the token for the rest of the session.
#+begin_src emacs-lisp
(with-eval-after-load 'lichess
(advice-add 'lichess-token :before
(lambda ()
(when (string-empty-p lichess-token)
(setq lichess-token
(string-trim (shell-command-to-string "pass lichess.org/token 2>/dev/null | head -1")))))))
#+end_src
** Beacon Remote Jobs
#+begin_src emacs-lisp
@@ -317,6 +493,62 @@ With prefix ARG, prompt for a pattern then select from matches."
(define-key azos/beacon/keymap (kbd "t") #'azos/beacon/tail-log)
#+end_src
** Roam Backup
=roam-backup= signs its commit with gpg, which can prompt for the YubiKey PIN
via pinentry. =async-shell-command= spawns the process with =TERM=dumb= and
no real controlling tty, so pinentry's curses fallback fails with
\"Inappropriate ioctl for device\" whenever the PIN cache has expired. Run it
in a =vterm= instead, which gives pinentry a real pty to prompt on.
#+begin_src emacs-lisp
(defun azos/roam/backup ()
"Commit and push ~/roam to the remote git repo."
(interactive)
(let ((vterm-buffer-name "*roam-backup*"))
(with-current-buffer (vterm-other-window)
(vterm-send-string "roam-backup")
(vterm-send-return))))
(define-key azos/roam-keymap (kbd "B") #'azos/roam/backup)
#+end_src
** Printing
#+begin_src emacs-lisp
(defun azos/print-buffer (&optional arg)
"Print the current buffer.
For image/PDF/doc buffers, sends the file path to lp directly.
For text buffers, uses lpr-buffer.
With C-u, interactively prompt for scaling, B&W, and orientation options."
(interactive "P")
(let* ((image-p (derived-mode-p 'image-mode 'pdf-view-mode 'doc-view-mode))
(scale (when arg (y-or-n-p "Fit to page? ")))
(bw (when arg (y-or-n-p "Black and white? ")))
(landscape (when (and arg image-p) (y-or-n-p "Landscape? ")))
(lp-opts (concat
(when scale " -o fit-to-page")
(when bw " -o print-color-mode=monochrome")
(when landscape " -o landscape"))))
(if image-p
(if buffer-file-name
(progn
(shell-command
(concat "lp" lp-opts " " (shell-quote-argument buffer-file-name)))
(message "Sent %s to printer%s%s%s."
(file-name-nondirectory buffer-file-name)
(if scale " [scaled]" "")
(if bw " [B&W]" "")
(if landscape " [landscape]" "")))
(error "Buffer has no associated file"))
(let ((lpr-switches
(append lpr-switches
(when bw '("-o print-color-mode=monochrome")))))
(lpr-buffer)))))
(define-key azos/global-minor-mode/open-keymap (kbd "P") #'azos/print-buffer)
#+end_src
* Provide
#+begin_src emacs-lisp
+19
View File
@@ -0,0 +1,19 @@
{...}: {
config.flake.modules.homeManager.leetcode = {
lib,
config,
pkgs,
...
}: {
options.azos.leetcode.enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.leetcode.enable {
azos.emacs.pkgs = [pkgs.azos-emacs-leetcode];
azos.emacs.enabledSuites = ["azos-emacs-leetcode"];
};
};
}
+14
View File
@@ -0,0 +1,14 @@
{
orgTrivialBuild,
epkgs,
pkgs,
}:
orgTrivialBuild {
pname = "azos-emacs-leetcode";
version = "0.1.0";
src = ./config.org;
packageRequires = with epkgs; [
pkgs.azos-emacs-base
leetcode
];
}
+29
View File
@@ -0,0 +1,29 @@
#+title: Aner's Emacs Leetcode Configuration
#+property: header-args :results silent
* Base setup
** Require
#+begin_src emacs-lisp
(require 'azos-emacs-base)
#+end_src
* Leetcode
#+begin_src emacs-lisp
(use-package leetcode
:init
(defun azos/leetcode/open ()
"Open leetcode in its dedicated \"leetcode\" tab."
(interactive)
(azos/tab-bar/open-singleton-tab "leetcode" #'leetcode))
:bind
(:map azos/global-minor-mode/open-keymap
("L" . azos/leetcode/open)))
#+end_src
* Provide
#+begin_src emacs-lisp
(provide 'azos-emacs-leetcode)
#+end_src
+3
View File
@@ -0,0 +1,3 @@
{...}: {
config.flake.overlayPkgs.azos-emacs-leetcode = pkgs: pkgs.localEmacsPkg ./_pkg.nix;
}
+16 -20
View File
@@ -2,15 +2,18 @@
config.flake.modules.homeManager.mail = {
lib,
config,
pkgs,
...
}: let
default_account_params = {
realName = "Aner Zakobar";
notmuch.enable = true;
mbsync = {
enable = true;
create = "maildir";
remove = "both";
expunge = "both";
};
msmtp.enable = true;
};
default_gmail_params =
default_account_params
@@ -20,45 +23,38 @@
default_smtp = {
tls = {
enable = true;
useStartTls = true;
certificatesFile = "/etc/ssl/certs/ca-certificates.crt";
};
};
in {
options.azos.mail.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.mail.enable {
programs = {
notmuch = {
enable = true;
hooks = {preNew = "mbsync -a";};
};
mbsync.enable = true;
msmtp.enable = true;
lieer.enable = true;
};
services.lieer.enable = true;
config = {
azos.mail.enable = true;
# mbsync's PassCmd shells out to `pass`, which needs the GPG smartcard to
# decrypt -- only meaningful to gate on when the smartcard/YubiKey setup
# is actually in play.
azos.mail.presenceCheckCommand = lib.mkIf config.azos.encryption.yubikey.enable "${pkgs.azos-card-present}/bin/azos-card-present";
accounts.email.accounts = {
gmail =
default_gmail_params
// {
address = "anerisgreat@gmail.com";
userName = "anerisgreat";
passwordCommand = "pass gmail.com/mbsync-anerisgreat";
passwordCommand = "pass mbsync/anerisgreat@gmail.com | head -1";
};
bgu =
default_gmail_params
// {
address = "anerz@post.bgu.ac.il";
userName = "anerz@post.bgu.ac.il";
passwordCommand = "pass post.bgu.ac.il/mbsync-anerz";
passwordCommand = "pass mbsync/anerz@post.bgu.ac.il | head -1";
};
zakobar =
default_account_params
// {
address = "aner@zakobar.com";
msmtp.enable = true;
primary = true;
userName = "aner@zakobar.com";
imap = {host = "mail.privateemail.com";};
@@ -68,7 +64,7 @@
port = 587;
host = "mail.privateemail.com";
};
passwordCommand = "pass zakobar.com/mail/aner";
passwordCommand = "pass privateemail.com | head -1";
};
};
};
+59 -2
View File
@@ -4,17 +4,74 @@
config,
pkgs,
...
}: {
}: let
mountDir = "synced-docs";
remoteSubfolder = "synced-docs";
remoteName = "ncsynceddocs";
remoteNameEnv = lib.toUpper remoteName;
# rclone's webdav backend needs the account's Nextcloud *user ID*, not
# its login name, in the /dav/files/<uid>/ path -- the two differ on
# this server. The login name ("aner") still goes in the `user` field
# for Basic Auth. Both the uid and password come from `pass` at service
# start, same as mbsync in features/mail, so neither lands in the Nix
# store.
#
# Shares the azos-card-present silent presence check (overlays/default.nix)
# with the mail sync timer: loop quietly until the YubiKey is plugged in
# (no pinentry prompt either way), then exec rclone in the foreground.
# Restart=always means unplugging/replugging the key remounts naturally.
nextcloudMountSafe = pkgs.writeShellScript "nextcloud-mount-safe" ''
set -eu
mountpoint="$HOME/${mountDir}"
${pkgs.coreutils}/bin/mkdir -p "$mountpoint"
while ! ${pkgs.azos-card-present}/bin/azos-card-present; do
${pkgs.coreutils}/bin/sleep 10
done
password=$(${pkgs.pass}/bin/pass zakobar.com | ${pkgs.coreutils}/bin/head -1)
uid=$(${pkgs.pass}/bin/pass nextcloud-username/aner | ${pkgs.coreutils}/bin/head -1)
export RCLONE_CONFIG_${remoteNameEnv}_TYPE=webdav
export RCLONE_CONFIG_${remoteNameEnv}_URL="https://nextcloud.zakobar.com/remote.php/dav/files/$uid/"
export RCLONE_CONFIG_${remoteNameEnv}_VENDOR=nextcloud
export RCLONE_CONFIG_${remoteNameEnv}_USER=aner
export RCLONE_CONFIG_${remoteNameEnv}_PASS="$(${pkgs.rclone}/bin/rclone obscure "$password")"
exec ${pkgs.rclone}/bin/rclone mount ${remoteName}:${remoteSubfolder} "$mountpoint" \
--vfs-cache-mode writes
'';
in {
options.azos.nextcloud-client.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.nextcloud-client.enable {
options.azos.nextcloud-mount.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkMerge [
(lib.mkIf config.azos.nextcloud-client.enable {
home.packages = with pkgs; [nextcloud-client];
services.nextcloud-client = {
enable = true;
startInBackground = false;
};
})
(lib.mkIf config.azos.nextcloud-mount.enable {
home.packages = with pkgs; [rclone];
# default.target, not graphical-session.target: the latter never
# activates under EXWM in this setup (nothing explicitly starts it),
# which is why nextcloud-client itself silently never autostarts.
systemd.user.services.nextcloud-mount = {
Unit.Description = "Mount Nextcloud ${remoteSubfolder} via rclone (waits silently for YubiKey)";
Service = {
Type = "simple";
Environment = "PATH=/run/wrappers/bin:${pkgs.fuse3}/bin:${pkgs.fuse}/bin";
ExecStart = "${nextcloudMountSafe}";
ExecStop = "/run/wrappers/bin/fusermount3 -u %h/${mountDir}";
Restart = "always";
RestartSec = "10s";
};
Install.WantedBy = ["default.target"];
};
})
];
};
}
+3
View File
@@ -58,3 +58,6 @@ c.fonts.hints = "bold 13px 'LiberationMono'"
#Set highdpi
c.qt.highdpi = True
c.zoom.default = 70
c.qt.args = ['--disable-gpu']
c.qt.environ = {'QT_XCB_GL_INTEGRATION': 'none', 'LIBGL_ALWAYS_SOFTWARE': '1'}
+1 -1
View File
@@ -5,7 +5,7 @@
...
}: {
options.azos.qutebrowser-config.enable = lib.mkOption {
default = true;
default = false;
type = lib.types.bool;
};
config = lib.mkIf config.azos.qutebrowser-config.enable {
+30
View File
@@ -0,0 +1,30 @@
{...}: {
config.flake.modules.homeManager.roam-backup = {
lib,
config,
pkgs,
...
}: {
options.azos.roam-backup.enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.roam-backup.enable {
home.packages = [
(pkgs.writeShellScriptBin "roam-backup" ''
set -e
cd "$HOME/roam"
git add -A
if git diff --cached --quiet; then
echo "Nothing to commit."
else
git commit -m "backup: $(date '+%Y-%m-%d %H:%M')"
fi
git push --set-upstream origin HEAD
'')
];
};
};
}
+1 -1
View File
@@ -9,7 +9,7 @@
in {
options.azos.snx-rs = {
enable = lib.mkOption {
default = true;
default = false;
type = lib.types.bool;
};
server = lib.mkOption {
+8
View File
@@ -10,6 +10,14 @@
};
config = lib.mkIf config.azos.steam.enable {
programs.steam.enable = true;
# HORI STICK A fight stick (0f0d:0040) is missing from Steam's bundled
# 60-steam-input.rules, so Steam can't open its hidraw node for Steam
# Input and falls back to a generic joystick mapping that drops BTN_C
# (Circle). Grant the same uaccess the other HORI devices get.
services.udev.extraRules = ''
KERNEL=="hidraw*", ATTRS{idVendor}=="0f0d", ATTRS{idProduct}=="0040", MODE="0660", TAG+="uaccess"
'';
};
};
}
-30
View File
@@ -1,30 +0,0 @@
{...}: {
config.flake.modules.nixos.virtualization = {
lib,
config,
pkgs,
...
}: {
options.azos.virtualization.enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.virtualization.enable {
virtualisation.libvirtd = {
enable = true;
qemu = {
swtpm.enable = true;
};
};
environment.systemPackages = with pkgs; [
qemu_kvm
libvirt
virt-manager
virt-viewer
];
services.spice-vdagentd.enable = true;
networking.firewall.allowedTCPPorts = [5900 5901];
networking.firewall.allowedUDPPorts = [5900 5901];
};
};
}
Generated
+76 -22
View File
@@ -56,6 +56,22 @@
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
@@ -79,11 +95,11 @@
"nixpkgs-lib": "nixpkgs-lib_2"
},
"locked": {
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"lastModified": 1788450739,
"narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993",
"type": "github"
},
"original": {
@@ -139,11 +155,11 @@
]
},
"locked": {
"lastModified": 1779969295,
"narHash": "sha256-HwIJ3tOcwSMiV75L7KqJXciXR9UfT+d7rwOZMX7cTnA=",
"lastModified": 1788651960,
"narHash": "sha256-v9wJd32eZ2bvhBzVOd7TIjLQd011P7nwOhjKtWlci5I=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "61e2c9659324181e0f0ed911958c536333b1d4f6",
"rev": "2c0350c759688177331b8f5242311fae8877bdb3",
"type": "github"
},
"original": {
@@ -170,11 +186,11 @@
},
"import-tree_2": {
"locked": {
"lastModified": 1778781969,
"narHash": "sha256-Jjuz5CmSkur8KvLDoGa+vylEp+RkQtv4mt/qcMznpH0=",
"lastModified": 1788467110,
"narHash": "sha256-ljEMTXP/rH0tOvDzc9gzwww6KcHRPRnEHzd9lK48V7s=",
"owner": "vic",
"repo": "import-tree",
"rev": "d321337efd0f23a9eb14a42adb7b2c29313ab274",
"rev": "eb1b52eaecc57f7c136d07ae8a93e724dfecac46",
"type": "github"
},
"original": {
@@ -202,12 +218,15 @@
}
},
"nixos-hardware": {
"inputs": {
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1779826373,
"narHash": "sha256-3sRzgLX86qV5NlhWUAufLmHwkyP03tmL3VdZIM13dEo=",
"lastModified": 1788335262,
"narHash": "sha256-3jBEq8avfzlrsY4UpW4d5TOmm7ocseZfnitEJhqauyc=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "ef4efb84766a166c906bd55759574676bf91267c",
"rev": "44d95795ee2d475b3d687325e26dcf4ca9104557",
"type": "github"
},
"original": {
@@ -217,6 +236,27 @@
"type": "github"
}
},
"nixos-wsl": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1784642409,
"narHash": "sha256-hcbDqFuySAJawljt5r0sKBCJKYnbtGD0T/ZIozH1Dq0=",
"owner": "nix-community",
"repo": "nixos-wsl",
"rev": "eaeb18da90024448a60eb1ec7132eafa4003404e",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixos-wsl",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1769421245,
@@ -248,11 +288,11 @@
},
"nixpkgs-lib_2": {
"locked": {
"lastModified": 1777168982,
"narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=",
"lastModified": 1788057806,
"narHash": "sha256-DTQSMxzDWmT0zhguthvegnVkn7CFqGCv4IHCzk5ZUpM=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "f5901329dade4a6ea039af1433fb087bd9c1fe14",
"rev": "596e2e3940e09b2abbeb03f75fa1828c57fcd72c",
"type": "github"
},
"original": {
@@ -263,11 +303,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1779560665,
"narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=",
"lastModified": 1788614874,
"narHash": "sha256-7QYjT2vHLuX9Z1pdxHXDKCbh1CR3D/2rywB9Tx0MPRg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786",
"rev": "c043004d1c6985732bcc1cbc5a9c9aecbbb4e0f0",
"type": "github"
},
"original": {
@@ -311,11 +351,24 @@
},
"nixpkgs_4": {
"locked": {
"lastModified": 1779877693,
"narHash": "sha256-NOF9NAREhxr50bbBfVcVOq+ArCMSoe8dP79Pk2uyARk=",
"lastModified": 1767892417,
"narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1788549839,
"narHash": "sha256-kOrCcSIA6w9J1hX5DqHy2k9pDTJymExTsbV74U9UtCA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4100e830e085863741bc69b156ec4ccd53ab5be0",
"rev": "17de0b976395537756f30a3e78f2f06e5cec89ed",
"type": "github"
},
"original": {
@@ -333,7 +386,8 @@
"import-tree": "import-tree_2",
"musnix": "musnix",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_4",
"nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs_5",
"nixpkgs-unstable": "nixpkgs-unstable"
}
},
+6
View File
@@ -21,6 +21,11 @@
flake = true;
};
nixos-wsl = {
url = "github:nix-community/nixos-wsl";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-parts.url = "github:hercules-ci/flake-parts";
import-tree.url = "github:vic/import-tree";
};
@@ -34,6 +39,7 @@
./_machines/lauretta.nix
./_machines/vm.nix
./_machines/beacon.nix
./_machines/beacon-wsl.nix
];
systems = [
+43 -7
View File
@@ -11,17 +11,12 @@
suiteModules.homeManager.base
suiteModules.homeManager.dev
suiteModules.homeManager.editor
suiteModules.homeManager.station
suiteModules.homeManager.desktop
suiteModules.homeManager.discord
suiteModules.homeManager.exwm
suiteModules.homeManager.lauretta
suiteModules.homeManager.audio
suiteModules.homeManager.claude
suiteModules.homeManager.encryption
suiteModules.homeManager.git-config
suiteModules.homeManager.hfsprogs
suiteModules.homeManager.headphones
suiteModules.homeManager.hyprland
suiteModules.homeManager.kubernetes
suiteModules.homeManager.mail
suiteModules.homeManager.mpris-proxy
suiteModules.homeManager.nextcloud
@@ -29,14 +24,55 @@
suiteModules.homeManager.qutebrowser
suiteModules.homeManager.reaper
suiteModules.homeManager.snx-rs
suiteModules.homeManager.roam-backup
suiteModules.homeManager.ytdl
suiteModules.homeManager.leetcode
];
programs.home-manager.enable = true;
azos.suites.lauretta.enable = true;
azos.chess.enable = true;
azos.leetcode.enable = true;
azos.name = "Aner Zakobar";
azos.headphones.enable = true;
azos.headphones.devices = [
{
mac = "AC:80:0A:AF:E1:C2";
name = "Aner's Headphones";
}
{
mac = "AC:80:0A:A1:5F:53";
name = "Chen's Headphones";
}
{
mac = "E4:17:D8:29:9B:16";
name = "8bitdo";
}
];
azos.roam-backup.enable = true;
azos.send-alert.enable = true;
azos.send-alert.remoteCommand = "${pkgs.azos-homey-ntfy-alert}/bin/azos-homey-ntfy-alert";
azos.git-config.userName = "Aner Zakobar";
azos.git-config.userEmail = "aner@zakobar.com";
azos.git-config.signing.enable = true;
azos.git-config.signing.key = "BB141234A3DD953D";
azos.git-config.passCredentialHelper.enable = true;
azos.git-config.passCredentialHelper.mapping = ''
[*git.zakobar.com*]
target=zakobar.com
'';
azos.encryption.passwordStore.gpgKeyId = "26B851F81F8F7C55";
azos.encryption.yubikey.enable = true;
azos.encryption.browserpass.enable = true;
azos.encryption.gpgSsh.enable = true;
azos.encryption.gpgSsh.keygrip = "37710BAB5F6DC9878A450CDA8A4661D932C04ACB";
azos.encryption.gpgSsh.publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDMdozJewuuqG4VuwGhI5Uw2xDIUrkQwyPGQ2q3tvnPq/VoV+zfdnou42I6XYEfOGd6xfLR0byOGCk1Ia1F/picBsxADEaJFBnTny5MWNA5MxwJIYUPW5+kFN1TmxdNGmj0WJ8qZeKkS3ffixdHlHTVu4Rzrlu8qDdw8TmgcvD7sHpNaBB+hwG9B/s5BAozfXvyXtW51lLLrEZdmUXJxAP51ubVgysZ985PA89o4G7LUE20IKAj3rgylLwq+Lz2PoGmVCptPTknLLzGlxTy2mU/tESJtS4iUvshSYiKak73BSen88xLWL/eZGFzOLW4TNem/qT0ykqK1s1BaGWCcQiDWN+Lpa3XqTbFN054MfhLdEMp+NjrdsCbZORzp9p2ZPDqi5jI1Hy7IN/8VzzB+T13MX6YhW7CBBqUZaivGhVQGsNjrFusPGhCaZrzNJ1l4qssLAlOh9qdaYzqDe+BIHsty55vw4Ph+Axou82babpLoiQzkCol2TWjPr7JSfHFkm6CmoTQ7mK8m7jRCodmxF+BEe4Usr+HrTKDc9fr5P4mdfL0O+ZPrlkPuG1zBTMal9MPxeCk4emzOZf7vBMNzb0aKHbOtSdVk/IcjatlDd2EIo34e5A6anLRMAdxb7901mnCAcjvCn6+ArNV8nr+NBk1+UvumZ+Q59LTrAkgRt3rBw== openpgp:0x13E0C25D";
home = {
username = "aner";
homeDirectory = "/home/aner";
+78
View File
@@ -0,0 +1,78 @@
{
lib,
config,
pkgs,
inputs,
suiteModules,
...
}: {
imports = [
inputs.nixos-wsl.nixosModules.default
suiteModules.nixos.attic
];
wsl.enable = true;
wsl.defaultUser = "aner";
nixpkgs.hostPlatform = "x86_64-linux";
nixpkgs.config.allowUnfree = true;
nix.settings = {
experimental-features = ["nix-command" "flakes"];
auto-optimise-store = true;
substituters = [
"https://cache.nixos.org"
"https://cuda-maintainers.cachix.org"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E="
];
};
security.sudo.wheelNeedsPassword = false;
networking.hostName = "beacon";
networking.firewall.allowedTCPPorts = [ 22 ];
programs.nix-ld.enable = true;
time.timeZone = "Asia/Jerusalem";
# GPU is exposed through WSL2 paravirtualization; no Linux NVIDIA KM needed
hardware.graphics.enable = true;
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
users.users.aner = {
isNormalUser = true;
extraGroups = ["wheel" "video"];
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDMdozJewuuqG4VuwGhI5Uw2xDIUrkQwyPGQ2q3tvnPq/VoV+zfdnou42I6XYEfOGd6xfLR0byOGCk1Ia1F/picBsxADEaJFBnTny5MWNA5MxwJIYUPW5+kFN1TmxdNGmj0WJ8qZeKkS3ffixdHlHTVu4Rzrlu8qDdw8TmgcvD7sHpNaBB+hwG9B/s5BAozfXvyXtW51lLLrEZdmUXJxAP51ubVgysZ985PA89o4G7LUE20IKAj3rgylLwq+Lz2PoGmVCptPTknLLzGlxTy2mU/tESJtS4iUvshSYiKak73BSen88xLWL/eZGFzOLW4TNem/qT0ykqK1s1BaGWCcQiDWN+Lpa3XqTbFN054MfhLdEMp+NjrdsCbZORzp9p2ZPDqi5jI1Hy7IN/8VzzB+T13MX6YhW7CBBqUZaivGhVQGsNjrFusPGhCaZrzNJ1l4qssLAlOh9qdaYzqDe+BIHsty55vw4Ph+Axou82babpLoiQzkCol2TWjPr7JSfHFkm6CmoTQ7mK8m7jRCodmxF+BEe4Usr+HrTKDc9fr5P4mdfL0O+ZPrlkPuG1zBTMal9MPxeCk4emzOZf7vBMNzb0aKHbOtSdVk/IcjatlDd2EIo34e5A6anLRMAdxb7901mnCAcjvCn6+ArNV8nr+NBk1+UvumZ+Q59LTrAkgRt3rBw== cardno:29_109_265"
];
};
environment.systemPackages = with pkgs; [
git
rsync
tmux
vim
wget
rclone
pciutils
nvtopPackages.nvidia
cudaPackages.cudatoolkit
cudaPackages.cudnn
cudaPackages.nccl
python3
direnv
];
azos.attic.enable = true;
system.stateVersion = "25.11";
}
+1 -1
View File
@@ -28,7 +28,7 @@
nixpkgs.config.cudaSupport = true;
nix.settings = {
experimental-features = "nix-command flakes";
experimental-features = ["nix-command" "flakes"];
auto-optimise-store = true;
substituters = [
"https://cache.nixos.org"
+1 -1
View File
@@ -47,7 +47,7 @@
config.nix.registry;
nix.settings = {
experimental-features = "nix-command flakes";
experimental-features = ["nix-command" "flakes"];
auto-optimise-store = true;
};
+20 -6
View File
@@ -14,18 +14,18 @@
inputs.home-manager.nixosModules.home-manager
suiteModules.nixos.base
suiteModules.nixos.exwm
suiteModules.nixos.audio
suiteModules.nixos.bluetooth
suiteModules.nixos.desktop
suiteModules.nixos.dev
suiteModules.nixos.steam
suiteModules.nixos.virtualization
suiteModules.nixos.binfmt
suiteModules.nixos.attic
suiteModules.nixos.hardware-auth
];
boot.loader.grub = {
enable = true;
efiSupport = true;
device = "nodev";
configurationLimit = 5;
};
boot.loader.efi.canTouchEfiVariables = true;
@@ -80,12 +80,26 @@
};
nix.settings = {
experimental-features = "nix-command flakes";
experimental-features = ["nix-command" "flakes"];
auto-optimise-store = true;
substituters = [
"https://cache.nixos.org"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
];
};
azos.suites.exwm.enable = true;
azos.attic.enable = true;
azos.printing.enable = true;
azos.printing.username = "aner";
azos.hardware-auth.enable = true;
# Needed for unprivileged FUSE mounts (e.g. rclone mount) -- without this,
# fusermount3 has no setuid wrapper and mounting fails with
# "Operation not permitted" even though /dev/fuse itself is world-writable.
programs.fuse.enable = true;
home-manager = {
extraSpecialArgs = {inherit inputs outputs suiteModules pkgs;};
@@ -108,7 +122,7 @@
services.greetd.settings = lib.mkForce {
terminal.vt = 1;
default_session = {
command = "${pkgs.tuigreet}/bin/tuigreet --time --user-menu --cmd '/home/aner/.login.sh'";
command = "${pkgs.tuigreet}/bin/tuigreet --time --user-menu --user-menu-min-uid 1000 --user-menu-max-uid 29999 --cmd '/home/aner/.login.sh'";
user = "greeter";
};
initial_session = {
+10
View File
@@ -11,4 +11,14 @@
config.allowUnfree = true;
};
};
# Shared silent presence check for the GPG smartcard (the YubiKey's OpenPGP
# applet): `gpg --card-status` only queries the reader, never invoking
# pinentry, so it's safe to poll without ever producing a "please insert
# card" prompt. Used by both the mail sync timer and the Nextcloud mount
# service to gate on `pass` being decryptable.
config.flake.overlayPkgs.azos-card-present = pkgs:
pkgs.writeShellScriptBin "azos-card-present" ''
exec ${pkgs.gnupg}/bin/gpg --card-status >/dev/null 2>&1
'';
}
-2
View File
@@ -1,5 +1,3 @@
{pkgs} @ args: {
#TODO since I do not pass along packages, this cannot work
# debugTex = import ./debugTex args;
default = import ./defaultShell.nix args;
}
+2 -1
View File
@@ -2,9 +2,10 @@
pkgs.mkShell {
buildInputs = with pkgs; [
alejandra
nh
(pkgs.writeShellScriptBin
"azos-lauretta-update"
"sudo nixos-rebuild switch --flake '.?submodules=1#lauretta'")
"nh os switch '.?submodules=1#lauretta'")
(pkgs.writeShellScriptBin
"azos-update-azos-core"
"nix flake update --flake '.?submodules=1' azos-core")