9 Commits

Author SHA1 Message Date
Fabio Scotto di Santolo
60f177f51c Add targeted Gufw compatibility for Sway sessions
- Remove the global xhost call from start-sway-session to keep Wayland startup clean
- Add a dedicated gufw wrapper and desktop override that temporarily grants Xwayland access only for gufw
2026-04-24 10:27:57 +02:00
Fabio Scotto di Santolo
dc25960f08 Replace Noctalia screenshot plugin with flameshot
- Switch Sway screenshot keybinds to flameshot and start it with the session
- Replace the Noctalia screenshot plugin with the official clipboard plugin and dedicated clipboard shortcuts
2026-04-24 10:27:13 +02:00
Fabio Scotto di Santolo
a57685d377 Desktop Sway: add xhost for polkit authentication compatibility 2026-04-24 00:26:39 +02:00
Fabio Scotto di Santolo
781f366fe7 Desktop Sway: add xorg-server-xwayland for X11 app compatibility 2026-04-24 00:07:23 +02:00
Fabio Scotto di Santolo
53b7baf52f Noctalia: add Network and Bluetooth to systray 2026-04-24 00:03:25 +02:00
Fabio Scotto di Santolo
525b0b0e42 Profile i3: remove unnecessary dunst/rofi directory creation
These directories are created automatically by the dotfiles copy task
in profile_desktop_i3, so hardcoding them in profile_desktop_common
unnecessarily creates them on Sway hosts.
2026-04-23 23:22:56 +02:00
Fabio Scotto di Santolo
57a605587a Set fixed wallpaper for Noctalia via wallpapers.json cache 2026-04-23 23:17:49 +02:00
Fabio Scotto di Santolo
8acd8204b9 Add i3 cleanup script for post-migration hosts
- Add a manual oneshot script to remove i3-only packages and configs after moving a host to SwayFX and Noctalia
- Support dry-run by default with optional apply and aggressive cleanup modes
2026-04-23 21:24:05 +02:00
Fabio Scotto di Santolo
e5b24fdf2c Align desktop theming around Noctalia Ayu
- Move Sway, GTK, Qt, Alacritty, and Emacs toward the Noctalia-generated Ayu theme
- Add shared font/cursor settings, qt5ct/qt6ct templates, and Flatpak theme integration support
- Keep browser and Telegram theming manual while preserving generated Noctalia assets where useful
2026-04-23 20:52:58 +02:00
83 changed files with 890 additions and 981 deletions

View File

@@ -1,7 +0,0 @@
{
"permissions": {
"allow": [
"Bash(xargs ls -la)"
]
}
}

0
.codex
View File

View File

@@ -6,9 +6,7 @@ Ansible-driven personal infrastructure repo for Void desktops, Linux workstation
- Main orchestration: `ansible/site.yml`
- Inventory and layering inputs: `ansible/inventory/hosts.yml`, `ansible/inventory/group_vars/*.yml`, `ansible/inventory/host_vars/*.yml`
- Dotfiles live under `dotfiles/`
- AI agent instructions (bootstrap, rules, knowledge) are centralized in `dotfiles/common/.config/ai/` and shared between OpenCode, Codex, and Gemini CLI.
- OpenCode loads its entrypoint configuration from `dotfiles/common/.config/opencode/opencode.json`.
- Codex config is rendered from `dotfiles/common/.codex/config.toml.j2` so `model_instructions_file` points to the deployed `~/.config/ai/bootstrap.md`.
- OpenCode loads global instructions from `dotfiles/desktop/.config/opencode/opencode.json`
## Topology
- Void desktops: `ikaros`, `nymph`
@@ -40,7 +38,7 @@ Ansible-driven personal infrastructure repo for Void desktops, Linux workstation
- WSL dev: `ansible-playbook ansible/site.yml --limit deadalus-wsl --check --diff`
- Server: `ansible-playbook ansible/site.yml --limit prometheus --check --diff`
- Focused checks:
- Emacs dotfiles only: `ansible-playbook ansible/site.yml --limit ikaros --tags emacs --check --diff` or `--limit nymph --tags emacs --check --diff`
- Emacs dotfiles only: `ansible-playbook ansible/site.yml --limit ikaros --tags emacs --check --diff` or `--limit nymph --tags emacs --check --diff`
- Sway/Noctalia bootstrap on nymph: `ansible-playbook ansible/site.yml --limit nymph --tags packages,dotfiles:desktop,sway --check --diff`
- Mail bootstrap: `sh -n scripts/bootstrap_mail.sh` and `shellcheck scripts/bootstrap_mail.sh`
- Windows bootstrap parse: `pwsh -NoProfile -Command "[void][System.Management.Automation.Language.Parser]::ParseFile('scripts/bootstrap_windows_workstation.ps1', [ref]$null, [ref]$null)"`
@@ -57,7 +55,6 @@ Ansible-driven personal infrastructure repo for Void desktops, Linux workstation
## Desktop Void Notes
- `profile_desktop_common` owns the shared desktop bootstrap.
- `.emacs.d` is deployed by a dedicated `profile_desktop_common` task tagged `emacs`.
- NTFS filesystem support is provided by `ntfs-3g` in `ansible/inventory/group_vars/void.yml`.
- User services are managed by `turnstile` and live under `dotfiles/desktop/.config/service/`.
- `ssh-agent` runs under `turnstile` with stable socket `~/.local/state/ssh-agent/socket`.
- Critical session entrypoints:
@@ -76,13 +73,6 @@ Ansible-driven personal infrastructure repo for Void desktops, Linux workstation
- `workstation_host_windows` runs with `gather_facts: false` and validates PSRP settings plus `windows_package_backend` before role execution.
- Windows taskbar pins are driven by `windows_taskbar_pins` in `ansible/inventory/group_vars/workstation_host_windows.yml`; validate identifiers from a real Windows session before changing them.
## Coding Agent Notes
- Shared agent packages live in `ai_agents_npm_packages` in `ansible/inventory/group_vars/all.yml`.
- Shared agent dotfiles live in `ai_agents_dotfiles`; rendered configs live in `ai_agents_templates`.
- Desktop, native workstation, and WSL profiles consume the shared agent package list; do not duplicate package entries in profile-specific vars.
- `dotfiles_common` copies common dotfiles plus `ai_agents_dotfiles`, then renders `ai_agents_templates`.
- Keep `.config/ai/` as the common instruction source; update agent-specific entrypoints to reference it rather than duplicating instruction text.
## Tooling Notes
- Install local tooling with:
- `python3 -m pip install ansible ansible-lint yamllint shellcheck-py`

691
README.md
View File

@@ -15,26 +15,26 @@ Il repository consente di gestire più sistemi operativi e profili macchina mant
# Architettura del progetto
```text
infra/
├── ansible/
│ ├── ansible.cfg
│ ├── site.yml
│ ├── inventory/
│ │ ├── hosts.yml
│ │ ├── group_vars/
│ │ └── host_vars/
│ ├── templates/
│ └── roles/
├── dotfiles/
│ ├── common/
│ ├── desktop/
│ ├── fedora/
│ ├── server/
│ ├── workstation/
│ ├── ikaros/
│ └── nymph/
```text
infra/
├── ansible/
│ ├── ansible.cfg
│ ├── site.yml
│ ├── inventory/
│ │ ├── hosts.yml
│ │ ├── group_vars/
│ │ └── host_vars/
│ ├── templates/
│ └── roles/
├── dotfiles/
│ ├── common/
│ ├── desktop/
│ ├── fedora/
│ ├── server/
│ ├── workstation/
│ ├── ikaros/
│ └── nymph/
├── scripts/
├── secrets/
@@ -50,16 +50,16 @@ Il repository è diviso in due componenti principali:
---
# Macchine gestite
Il repository modella attualmente tre tipologie di profilo e prepara due filoni workstation: Linux nativa e Windows + WSL.
Nota sullo stato attuale del playbook principale:
- `ansible/site.yml` applica oggi in automatico il profilo desktop su host Void Linux
- `ansible/site.yml` applica la workstation Linux nativa separando il layer dev comune dal layer host GNOME
- `ansible/site.yml` applica anche il ramo `workstation_host_windows` + `workstation_dev_wsl` per il modello Windows 11 + WSL
- `ansible/site.yml` applica anche il profilo `ubuntu_server` con baseline apt, systemd, dotfiles server e firewall UFW
# Macchine gestite
Il repository modella attualmente tre tipologie di profilo e prepara due filoni workstation: Linux nativa e Windows + WSL.
Nota sullo stato attuale del playbook principale:
- `ansible/site.yml` applica oggi in automatico il profilo desktop su host Void Linux
- `ansible/site.yml` applica la workstation Linux nativa separando il layer dev comune dal layer host GNOME
- `ansible/site.yml` applica anche il ramo `workstation_host_windows` + `workstation_dev_wsl` per il modello Windows 11 + WSL
- `ansible/site.yml` applica anche il profilo `ubuntu_server` con baseline apt, systemd, dotfiles server e firewall UFW
## Desktop
@@ -67,18 +67,18 @@ Sistema operativo:
- Void Linux
Sessioni desktop:
- `ikaros`: i3
- `nymph`: SwayFX
Sessioni desktop:
- `ikaros`: i3
- `nymph`: SwayFX
Macchine:
- `ikaros`
- `nymph`
Queste macchine condividono la stessa configurazione base desktop e vengono mantenute allineate tramite Ansible.
Queste macchine condividono la stessa configurazione base desktop e vengono mantenute allineate tramite Ansible.
Lo stato attuale del profilo desktop include, tra le altre cose:
- dotfiles comuni e desktop
@@ -91,87 +91,87 @@ Lo stato attuale del profilo desktop include, tra le altre cose:
- `tmux` con plugin gestiti da TPM al bootstrap del profilo desktop
- Flatpak con remoto Flathub
- GNOME Keyring e bootstrap della posta via script dedicato
- shell Noctalia su Sway su `nymph`, con plugin ufficiali per clipboard (`clipper`), polkit (`polkit-agent`), screenshot (`screenshot`) e gestione USB (`usb-drive-manager`); config condivisa in `dotfiles/desktop/.config/noctalia/` e `settings.json` renderizzato da template Ansible con variabili host-specifiche
- shell Noctalia su Sway su `nymph`, con plugin ufficiali per clipboard (`clipper`, `clipboard`), polkit (`polkit-agent`) e gestione USB (`usb-drive-manager`); config condivisa in `dotfiles/desktop/.config/noctalia/` e `settings.json` renderizzato da template Ansible con variabili host-specifiche
- `udiskie` come backend per automount/LUKS su Sway, senza tray; la UI dei dispositivi removibili è demandata a `usb-drive-manager`
- `kanshi` su `nymph` per il profilo monitor Wayland, con workspace Sway deterministici: in dual monitor `1` resta su `eDP-1` e `2-10` vanno su `DP-1`, mentre in laptop-only tutti tornano su `eDP-1`
- monitor Noctalia e `screenOverrides` dichiarati in inventory (`noctalia_bar_monitors`, `noctalia_screen_overrides`) per host `nymph`
- monitor Noctalia e `screenOverrides` dichiarati in inventory (`noctalia_bar_monitors`, `noctalia_screen_overrides`) per host `nymph`
---
## Workstation
## Workstation
Sistemi operativi supportati:
Sistemi operativi supportati:
- Ubuntu LTS nativa
- Fedora Workstation nativa
- Windows 11 host + Ubuntu WSL
- Ubuntu LTS nativa
- Fedora Workstation nativa
- Windows 11 host + Ubuntu WSL
Desktop environment host Linux:
- GNOME
Macchine attuali:
- `deadalus-ubuntu` come workstation Ubuntu nativa
- `deadalus-fedora` come workstation Fedora nativa
- supporto attivo per host Windows 11 + WSL tramite `deadalus-win` e `deadalus-wsl`
Questo profilo è pensato per sviluppo e lavoro, con separazione tra layer host e layer dev.
Nel modello Ansible usato qui, un singolo inventory host puo appartenere intenzionalmente a piu gruppi e quindi ricevere piu play nello stesso run: l'associazione non e `1 host = 1 play`, ma `host + gruppi = layering finale`.
Il profilo workstation e agganciato al playbook principale e ora distingue:
- layer dev Ubuntu condiviso tra workstation Linux nativa e Ubuntu in WSL
- layer dev Fedora nativo parallelo a Ubuntu
- layer host Linux GNOME
- layer host Windows 11 con bootstrap WSL, remoting `PSRP` su `HTTPS/5986`, gestione app via `winget` con backend configurabile e VS Code lato Windows
- layer WSL dedicato per sviluppo con `systemd`
Per esempio, lo stesso host Linux puo stare in `workstation_host_linux` e in `workstation_dev_fedora` oppure `workstation_dev_ubuntu`, a seconda del layering che vuoi comporre.
Lo stato attuale del profilo workstation include:
- installazione pacchetti base Ubuntu via apt
- installazione pacchetti base Fedora via dnf per il ramo workstation nativo
- installazione e configurazione di Docker dal repository ufficiale
- gestione dei dotfiles workstation e rendering dei template dev condivisi
- installazione di Google Chrome su Ubuntu e Fedora, `VS Code` su Fedora via repository RPM Microsoft, `IntelliJ IDEA Ultimate` su Fedora via COPR RPM, e applicazioni workstation residue su Fedora via Flatpak
- installazione di applicazioni workstation su Ubuntu nativa via Snap, oltre alle estensioni GNOME sul solo host Linux nativo
- configurazione del ramo Windows 11 host con app installate dal playbook via `winget`, con backend predefinito `winget_psrp`, tema scuro, pin della taskbar gestiti via policy locale e profilo predefinito di Windows Terminal impostato su `Ubuntu`
- preparazione del ramo WSL Ubuntu con `systemd` per il toolchain di sviluppo
- attivazione del firewall UFW su Ubuntu nativa e `firewalld` su Fedora nativa
- gestione di `gsettings` GNOME host-specifici su `deadalus-fedora`, inclusi shell, Files/Nautilus, file chooser GTK e GNOME Text Editor, allineati allo stato reale della macchina
Workflow Windows + WSL previsto:
Prima di eseguire il bootstrap Windows, apri PowerShell come amministratore e verifica la policy di esecuzione:
```powershell
Get-ExecutionPolicy -List
```
Se necessario, abilita l'esecuzione degli script per l'utente corrente:
```powershell
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
```
Se Windows ha bloccato il file di bootstrap, sbloccalo esplicitamente:
```powershell
Unblock-File .\scripts\bootstrap_windows_workstation.ps1
```
1. eseguire `scripts/bootstrap_windows_workstation.ps1` su Windows come amministratore
2. riavviare Windows se richiesto dalle feature WSL
3. avviare Ubuntu WSL almeno una volta e completare la creazione dell'utente Linux
4. installare Ansible dentro WSL Ubuntu
5. lanciare il playbook da WSL su `deadalus-wsl` per configurare l'ambiente dev locale
6. lanciare da WSL anche il playbook su `deadalus-win` via `psrp` per configurare l'host Windows; per default il backend pacchetti Windows e `winget_psrp`
7. usare VS Code con le estensioni Remote (`WSL`, `SSH`, `Dev Containers`) dal lato Windows
Per il remoting Windows il repository usa di default `PSRP` con `Negotiate` su `HTTPS/5986`. L'utente di default puo essere un `MicrosoftAccount\...`, con host, utente e password forniti via vault o extra vars. Il backend pacchetti Windows e configurabile con `windows_package_backend` oppure `vault_windows_package_backend`; il default e `winget_psrp`.
Desktop environment host Linux:
- GNOME
Macchine attuali:
- `deadalus-ubuntu` come workstation Ubuntu nativa
- `deadalus-fedora` come workstation Fedora nativa
- supporto attivo per host Windows 11 + WSL tramite `deadalus-win` e `deadalus-wsl`
Questo profilo è pensato per sviluppo e lavoro, con separazione tra layer host e layer dev.
Nel modello Ansible usato qui, un singolo inventory host puo appartenere intenzionalmente a piu gruppi e quindi ricevere piu play nello stesso run: l'associazione non e `1 host = 1 play`, ma `host + gruppi = layering finale`.
Il profilo workstation e agganciato al playbook principale e ora distingue:
- layer dev Ubuntu condiviso tra workstation Linux nativa e Ubuntu in WSL
- layer dev Fedora nativo parallelo a Ubuntu
- layer host Linux GNOME
- layer host Windows 11 con bootstrap WSL, remoting `PSRP` su `HTTPS/5986`, gestione app via `winget` con backend configurabile e VS Code lato Windows
- layer WSL dedicato per sviluppo con `systemd`
Per esempio, lo stesso host Linux puo stare in `workstation_host_linux` e in `workstation_dev_fedora` oppure `workstation_dev_ubuntu`, a seconda del layering che vuoi comporre.
Lo stato attuale del profilo workstation include:
- installazione pacchetti base Ubuntu via apt
- installazione pacchetti base Fedora via dnf per il ramo workstation nativo
- installazione e configurazione di Docker dal repository ufficiale
- gestione dei dotfiles workstation e rendering dei template dev condivisi
- installazione di Google Chrome su Ubuntu e Fedora, `VS Code` su Fedora via repository RPM Microsoft, `IntelliJ IDEA Ultimate` su Fedora via COPR RPM, e applicazioni workstation residue su Fedora via Flatpak
- installazione di applicazioni workstation su Ubuntu nativa via Snap, oltre alle estensioni GNOME sul solo host Linux nativo
- configurazione del ramo Windows 11 host con app installate dal playbook via `winget`, con backend predefinito `winget_psrp`, tema scuro, pin della taskbar gestiti via policy locale e profilo predefinito di Windows Terminal impostato su `Ubuntu`
- preparazione del ramo WSL Ubuntu con `systemd` per il toolchain di sviluppo
- attivazione del firewall UFW su Ubuntu nativa e `firewalld` su Fedora nativa
- gestione di `gsettings` GNOME host-specifici su `deadalus-fedora`, inclusi shell, Files/Nautilus, file chooser GTK e GNOME Text Editor, allineati allo stato reale della macchina
Workflow Windows + WSL previsto:
Prima di eseguire il bootstrap Windows, apri PowerShell come amministratore e verifica la policy di esecuzione:
```powershell
Get-ExecutionPolicy -List
```
Se necessario, abilita l'esecuzione degli script per l'utente corrente:
```powershell
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
```
Se Windows ha bloccato il file di bootstrap, sbloccalo esplicitamente:
```powershell
Unblock-File .\scripts\bootstrap_windows_workstation.ps1
```
1. eseguire `scripts/bootstrap_windows_workstation.ps1` su Windows come amministratore
2. riavviare Windows se richiesto dalle feature WSL
3. avviare Ubuntu WSL almeno una volta e completare la creazione dell'utente Linux
4. installare Ansible dentro WSL Ubuntu
5. lanciare il playbook da WSL su `deadalus-wsl` per configurare l'ambiente dev locale
6. lanciare da WSL anche il playbook su `deadalus-win` via `psrp` per configurare l'host Windows; per default il backend pacchetti Windows e `winget_psrp`
7. usare VS Code con le estensioni Remote (`WSL`, `SSH`, `Dev Containers`) dal lato Windows
Per il remoting Windows il repository usa di default `PSRP` con `Negotiate` su `HTTPS/5986`. L'utente di default puo essere un `MicrosoftAccount\...`, con host, utente e password forniti via vault o extra vars. Il backend pacchetti Windows e configurabile con `windows_package_backend` oppure `vault_windows_package_backend`; il default e `winget_psrp`.
---
@@ -189,43 +189,43 @@ Macchina:
- `prometheus`
Profilo orientato a servizi server e gestione di dotfiles dedicati.
Lo stato attuale del profilo server include:
- installazione pacchetti base Ubuntu via apt
- installazione e configurazione di Docker dal repository ufficiale
- abilitazione dei servizi systemd dichiarati in inventory/group vars
- copia dei dotfiles server e rendering dei template server, incluso il `docker-compose.yml` dello stack servizi
- attivazione del firewall UFW con regola SSH esplicita
- apertura delle porte Syncthing `22000/tcp`, `22000/udp` e `21027/udp`, lasciando la GUI non esposta direttamente su UFW
Utente del profilo server:
- il profilo usa `server_username`, `server_user_group` e `server_user_home` definiti in `ansible/inventory/group_vars/server.yml`
- per default `server_username` eredita `username`, ma puo essere sovrascritto per tutti gli host server via inventory oppure a runtime con extra vars
- esempio override da CLI:
```bash
ansible-playbook ansible/site.yml --limit prometheus -e server_username=myuser
```
- se necessario puoi passare anche:
```bash
ansible-playbook ansible/site.yml --limit prometheus -e server_username=myuser -e server_user_group=mygroup -e server_user_home=/srv/myuser
```
Profilo orientato a servizi server e gestione di dotfiles dedicati.
Lo stato attuale del profilo server include:
- installazione pacchetti base Ubuntu via apt
- installazione e configurazione di Docker dal repository ufficiale
- abilitazione dei servizi systemd dichiarati in inventory/group vars
- copia dei dotfiles server e rendering dei template server, incluso il `docker-compose.yml` dello stack servizi
- attivazione del firewall UFW con regola SSH esplicita
- apertura delle porte Syncthing `22000/tcp`, `22000/udp` e `21027/udp`, lasciando la GUI non esposta direttamente su UFW
Utente del profilo server:
- il profilo usa `server_username`, `server_user_group` e `server_user_home` definiti in `ansible/inventory/group_vars/server.yml`
- per default `server_username` eredita `username`, ma puo essere sovrascritto per tutti gli host server via inventory oppure a runtime con extra vars
- esempio override da CLI:
```bash
ansible-playbook ansible/site.yml --limit prometheus -e server_username=myuser
```
- se necessario puoi passare anche:
```bash
ansible-playbook ansible/site.yml --limit prometheus -e server_username=myuser -e server_user_group=mygroup -e server_user_home=/srv/myuser
```
---
# Composizione della configurazione
Deploy mirato della configurazione Emacs sui desktop Void:
```bash
ansible-playbook ansible/site.yml --limit ikaros --tags emacs
ansible-playbook ansible/site.yml --limit nymph --tags emacs
```
# Composizione della configurazione
Deploy mirato della configurazione Emacs sui desktop Void:
```bash
ansible-playbook ansible/site.yml --limit ikaros --tags emacs
ansible-playbook ansible/site.yml --limit nymph --tags emacs
```
La configurazione finale di una macchina è ottenuta combinando più livelli.
@@ -258,67 +258,67 @@ Questo approccio consente di:
# Ruoli Ansible
I principali ruoli attualmente presenti sono:
I principali ruoli attualmente presenti sono:
| Role | Descrizione |
| ------------------------- | ----------------------------------- |
| base | configurazione base comune |
| packages_void | installazione pacchetti su Void |
| packages_ubuntu | installazione pacchetti su Ubuntu |
| packages_fedora | installazione pacchetti su Fedora |
| services_runit | gestione servizi runit |
| services_systemd | gestione servizi systemd |
| profile_desktop_common | bootstrap desktop Void condiviso |
| profile_desktop_i3 | sessione desktop i3 |
| profile_desktop_sway | sessione desktop Sway |
| profile_desktop_host | override desktop specifici per host |
| profile_workstation_dev_common | configurazione dev workstation condivisa |
| profile_workstation_gnome | configurazione host workstation GNOME |
| profile_workstation_dev_wsl | configurazione WSL Ubuntu per sviluppo |
| profile_workstation_host_windows | configurazione host Windows 11 workstation |
| profile_server | configurazione server |
| dotfiles_common | distribuzione dotfiles comuni |
| dotfiles | distribuzione configurazioni utente |
---
# Stato attuale del playbook principale
Il playbook `ansible/site.yml` e attualmente composto da sette blocchi:
```text
all:!workstation_host_windows -> dotfiles_common
void -> packages_void + services_runit + profile_desktop_common + profile_desktop_i3 + profile_desktop_sway + profile_desktop_host
workstation_dev_ubuntu -> packages_ubuntu + services_systemd + profile_workstation_dev_common
workstation_dev_fedora -> packages_fedora + services_systemd + profile_workstation_dev_common
workstation_host_linux -> profile_workstation_gnome
workstation_dev_wsl -> packages_ubuntu + services_systemd + profile_workstation_dev_common + profile_workstation_dev_wsl
workstation_host_windows -> profile_workstation_host_windows
ubuntu_server -> packages_ubuntu + services_systemd + profile_server
```
Questo significa che, allo stato attuale:
- i desktop Void (`ikaros`, `nymph`) restano il target operativo piu completo
- la workstation Ubuntu (`deadalus-ubuntu`) e gestita separando ambiente dev e layer host GNOME
- la workstation Fedora (`deadalus-fedora`) usa lo stesso principio di composizione a gruppi con il ramo Fedora dedicato e con `gsettings` host-specifici dichiarati in inventory
- il ramo Windows + WSL e predisposto con bootstrap PowerShell e play Windows/WSL dedicati
- il server Ubuntu (`prometheus`) e gestito con pacchetti, servizi, dotfiles server e firewall
- lo stack container server include `navidrome`, `postgres`, `gitea`, `nginx-proxy-manager` e `syncthing`, con GUI Syncthing raggiungibile tramite la rete Docker `web`
# Dotfiles
| base | configurazione base comune |
| packages_void | installazione pacchetti su Void |
| packages_ubuntu | installazione pacchetti su Ubuntu |
| packages_fedora | installazione pacchetti su Fedora |
| services_runit | gestione servizi runit |
| services_systemd | gestione servizi systemd |
| profile_desktop_common | bootstrap desktop Void condiviso |
| profile_desktop_i3 | sessione desktop i3 |
| profile_desktop_sway | sessione desktop Sway |
| profile_desktop_host | override desktop specifici per host |
| profile_workstation_dev_common | configurazione dev workstation condivisa |
| profile_workstation_gnome | configurazione host workstation GNOME |
| profile_workstation_dev_wsl | configurazione WSL Ubuntu per sviluppo |
| profile_workstation_host_windows | configurazione host Windows 11 workstation |
| profile_server | configurazione server |
| dotfiles_common | distribuzione dotfiles comuni |
| dotfiles | distribuzione configurazioni utente |
---
# Stato attuale del playbook principale
Il playbook `ansible/site.yml` e attualmente composto da sette blocchi:
```text
all:!workstation_host_windows -> dotfiles_common
void -> packages_void + services_runit + profile_desktop_common + profile_desktop_i3 + profile_desktop_sway + profile_desktop_host
workstation_dev_ubuntu -> packages_ubuntu + services_systemd + profile_workstation_dev_common
workstation_dev_fedora -> packages_fedora + services_systemd + profile_workstation_dev_common
workstation_host_linux -> profile_workstation_gnome
workstation_dev_wsl -> packages_ubuntu + services_systemd + profile_workstation_dev_common + profile_workstation_dev_wsl
workstation_host_windows -> profile_workstation_host_windows
ubuntu_server -> packages_ubuntu + services_systemd + profile_server
```
Questo significa che, allo stato attuale:
- i desktop Void (`ikaros`, `nymph`) restano il target operativo piu completo
- la workstation Ubuntu (`deadalus-ubuntu`) e gestita separando ambiente dev e layer host GNOME
- la workstation Fedora (`deadalus-fedora`) usa lo stesso principio di composizione a gruppi con il ramo Fedora dedicato e con `gsettings` host-specifici dichiarati in inventory
- il ramo Windows + WSL e predisposto con bootstrap PowerShell e play Windows/WSL dedicati
- il server Ubuntu (`prometheus`) e gestito con pacchetti, servizi, dotfiles server e firewall
- lo stack container server include `navidrome`, `postgres`, `gitea`, `nginx-proxy-manager` e `syncthing`, con GUI Syncthing raggiungibile tramite la rete Docker `web`
# Dotfiles
La directory `dotfiles/` contiene le configurazioni utente versionate.
```text
dotfiles/
├── common
├── desktop
├── server
├── fedora
├── workstation
├── ikaros
└── nymph
```text
dotfiles/
├── common
├── desktop
├── server
├── fedora
├── workstation
├── ikaros
└── nymph
```
Le configurazioni sono applicate tramite Ansible e organizzate per livelli:
@@ -333,154 +333,153 @@ Le configurazioni sono applicate tramite Ansible e organizzate per livelli:
# Requisiti
Per utilizzare il repository sono necessari:
- Python 3
- Ansible
- `ansible-lint`
- `yamllint`
- `shellcheck`
- collection definite in `ansible/collections/requirements.yml`
- accesso locale o SSH alle macchine target, in base a come e definito l'inventory
Installazione base:
```bash
python3 -m pip install ansible ansible-lint yamllint shellcheck-py
ansible-galaxy collection install -r ansible/collections/requirements.yml
```
Gestione segreti:
- il repository supporta il caricamento opzionale di `secrets/vault.yml`
- il repository supporta anche `secrets/vault.local.yml` per override locali non versionati
- `secrets/vault.yml.example` funge da template/esempio
- se `secrets/vault.yml` non e presente, il playbook continua comunque senza caricare variabili locali opzionali
- se `secrets/.vault_pass.gpg` esiste viene usato automaticamente per sbloccare i vault tramite `gpg`; in alternativa resta supportato `secrets/.vault_pass` come fallback legacy locale; se nessuno dei due file esiste Ansible richiede la password in modo interattivo
- per il ramo Windows puoi anche definire `vault_windows_package_backend`, con valori supportati `winget_psrp` e `winget_wsl_local`; il default e `winget_psrp`
Per utilizzare il repository sono necessari:
- Python 3
- Ansible
- `ansible-lint`
- `yamllint`
- `shellcheck`
- collection definite in `ansible/collections/requirements.yml`
- accesso locale o SSH alle macchine target, in base a come e definito l'inventory
Installazione base:
```bash
python3 -m pip install ansible ansible-lint yamllint shellcheck-py
ansible-galaxy collection install -r ansible/collections/requirements.yml
```
Gestione segreti:
- il repository supporta il caricamento opzionale di `secrets/vault.yml`
- il repository supporta anche `secrets/vault.local.yml` per override locali non versionati
- `secrets/vault.yml.example` funge da template/esempio
- se `secrets/vault.yml` non e presente, il playbook continua comunque senza caricare variabili locali opzionali
- se `secrets/.vault_pass.gpg` esiste viene usato automaticamente per sbloccare i vault tramite `gpg`; in alternativa resta supportato `secrets/.vault_pass` come fallback legacy locale; se nessuno dei due file esiste Ansible richiede la password in modo interattivo
- per il ramo Windows puoi anche definire `vault_windows_package_backend`, con valori supportati `winget_psrp` e `winget_wsl_local`; il default e `winget_psrp`
---
# Utilizzo
Eseguire il playbook principale:
```bash
ansible-playbook ansible/site.yml
```
Allo stato attuale questo comando:
- distribuisce i dotfiles comuni a tutti gli host
- per gli host Void applica bootstrap desktop condiviso, sessioni i3/Sway e override specifici per host
- per `workstation_dev_ubuntu` applica pacchetti Ubuntu, servizi systemd e profilo dev comune
- per `workstation_dev_fedora` applica pacchetti Fedora, servizi systemd e profilo dev comune
- per `workstation_host_linux` applica il layer host Linux GNOME
- per `workstation_dev_wsl` applica pacchetti Ubuntu, servizi systemd, profilo dev comune e tweak WSL dedicati
- per `workstation_host_windows` applica il layer host Windows 11 via PSRP, con installazione pacchetti Windows eseguita di default tramite `winget_psrp`
- per gli host `ubuntu_server` applica pacchetti Ubuntu, servizi systemd, profilo server, UFW, dotfiles e template dedicati
- non riavvia automaticamente `emptty`; le modifiche al display manager vanno applicate manualmente da SSH o da una TTY separata
- carica `secrets/vault.yml` solo se presente
- carica `secrets/vault.local.yml` solo se presente, dopo `vault.yml`, cosi gli override locali hanno precedenza
Per validare prima di applicare:
```bash
ansible-playbook ansible/site.yml --syntax-check
ansible-playbook ansible/site.yml --limit ikaros --check --diff
ansible-playbook ansible/site.yml --limit nymph --check --diff
ansible-playbook ansible/site.yml --limit deadalus-ubuntu --check --diff
ansible-playbook ansible/site.yml --limit deadalus-fedora --check --diff
ansible-playbook ansible/site.yml --limit deadalus-wsl --check --diff
ansible-playbook ansible/site.yml --limit prometheus --check --diff
ansible-lint ansible/site.yml
ansible-lint ansible/roles
yamllint ansible/
```
Per testare un override dell'utente server senza modificare l'inventory:
```bash
ansible-playbook ansible/site.yml --limit prometheus --check --diff -e server_username=myuser
```
Per validazioni piu mirate:
```bash
ansible-playbook ansible/site.yml --limit <host> --tags <tag1>,<tag2> --check --diff
ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff
ansible-lint ansible/roles/<role>
yamllint ansible/path/to/file.yml
docker compose -f /opt/docker/server/docker-compose.yml config
```
## Tag supportati dal playbook
Per vedere l'elenco reale aggiornato dei tag disponibili:
```bash
ansible-playbook ansible/site.yml --list-tags
```
Allo stato attuale `ansible/site.yml` espone questi tag:
| Tag | Scopo | Ambito principale |
| --- | --- | --- |
| `always` | pre-task sempre eseguiti, inclusi caricamento vault e validazioni preliminari | common, Windows |
| `dotfiles` | distribuzione/configurazione dotfiles | tutti i profili |
| `dotfiles:common` | dotfiles comuni condivisi | common, workstation, server |
| `dotfiles:desktop` | dotfiles desktop | desktop Void |
| `dotfiles:host` | override host-specifici desktop | desktop Void |
| `dotfiles:server` | dotfiles dedicati al profilo server | server |
| `dotfiles:workstation` | dotfiles dedicati alle workstation | workstation Linux, WSL |
| `emptty` | gestione display manager `emptty` | desktop Void |
| `gnome` | configurazione host GNOME | workstation host Linux, parte desktop |
| `i3` | sessione/configurazione i3 | desktop Void |
| `npm` | installazione pacchetti npm globali | desktop Void, workstation Linux, WSL |
| `nvidia` | componenti NVIDIA desktop | desktop Void |
| `packages` | installazione e aggiornamento pacchetti | tutti i profili |
| `services` | gestione servizi runit/systemd/Windows | tutti i profili |
| `sway` | sessione/configurazione Sway | desktop Void |
| `vscode` | installazione/configurazione VS Code | Fedora, host Linux, Windows |
| `wsl` | bootstrap e configurazione WSL | WSL, Windows |
Esempi pratici:
```bash
ansible-playbook ansible/site.yml --limit nymph --tags dotfiles:desktop,sway --check --diff
ansible-playbook ansible/site.yml --limit deadalus-fedora --tags packages,vscode --check --diff
ansible-playbook ansible/site.yml --limit prometheus --tags services,dotfiles:server --check --diff
```
---
Eseguire il playbook principale:
```bash
ansible-playbook ansible/site.yml
```
Allo stato attuale questo comando:
- distribuisce i dotfiles comuni a tutti gli host
- per gli host Void applica bootstrap desktop condiviso, sessioni i3/Sway e override specifici per host
- per `workstation_dev_ubuntu` applica pacchetti Ubuntu, servizi systemd e profilo dev comune
- per `workstation_dev_fedora` applica pacchetti Fedora, servizi systemd e profilo dev comune
- per `workstation_host_linux` applica il layer host Linux GNOME
- per `workstation_dev_wsl` applica pacchetti Ubuntu, servizi systemd, profilo dev comune e tweak WSL dedicati
- per `workstation_host_windows` applica il layer host Windows 11 via PSRP, con installazione pacchetti Windows eseguita di default tramite `winget_psrp`
- per gli host `ubuntu_server` applica pacchetti Ubuntu, servizi systemd, profilo server, UFW, dotfiles e template dedicati
- non riavvia automaticamente `emptty`; le modifiche al display manager vanno applicate manualmente da SSH o da una TTY separata
- carica `secrets/vault.yml` solo se presente
- carica `secrets/vault.local.yml` solo se presente, dopo `vault.yml`, cosi gli override locali hanno precedenza
Per validare prima di applicare:
```bash
ansible-playbook ansible/site.yml --syntax-check
ansible-playbook ansible/site.yml --limit ikaros --check --diff
ansible-playbook ansible/site.yml --limit nymph --check --diff
ansible-playbook ansible/site.yml --limit deadalus-ubuntu --check --diff
ansible-playbook ansible/site.yml --limit deadalus-fedora --check --diff
ansible-playbook ansible/site.yml --limit deadalus-wsl --check --diff
ansible-playbook ansible/site.yml --limit prometheus --check --diff
ansible-lint ansible/site.yml
ansible-lint ansible/roles
yamllint ansible/
```
Per testare un override dell'utente server senza modificare l'inventory:
```bash
ansible-playbook ansible/site.yml --limit prometheus --check --diff -e server_username=myuser
```
Per validazioni piu mirate:
```bash
ansible-playbook ansible/site.yml --limit <host> --tags <tag1>,<tag2> --check --diff
ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff
ansible-lint ansible/roles/<role>
yamllint ansible/path/to/file.yml
docker compose -f /opt/docker/server/docker-compose.yml config
```
## Tag supportati dal playbook
Per vedere l'elenco reale aggiornato dei tag disponibili:
```bash
ansible-playbook ansible/site.yml --list-tags
```
Allo stato attuale `ansible/site.yml` espone questi tag:
| Tag | Scopo | Ambito principale |
| --- | --- | --- |
| `always` | pre-task sempre eseguiti, inclusi caricamento vault e validazioni preliminari | common, Windows |
| `dotfiles` | distribuzione/configurazione dotfiles | tutti i profili |
| `dotfiles:common` | dotfiles comuni condivisi | common, workstation, server |
| `dotfiles:desktop` | dotfiles desktop | desktop Void |
| `dotfiles:host` | override host-specifici desktop | desktop Void |
| `dotfiles:server` | dotfiles dedicati al profilo server | server |
| `dotfiles:workstation` | dotfiles dedicati alle workstation | workstation Linux, WSL |
| `emptty` | gestione display manager `emptty` | desktop Void |
| `gnome` | configurazione host GNOME | workstation host Linux, parte desktop |
| `i3` | sessione/configurazione i3 | desktop Void |
| `nvidia` | componenti NVIDIA desktop | desktop Void |
| `packages` | installazione e aggiornamento pacchetti | tutti i profili |
| `services` | gestione servizi runit/systemd/Windows | tutti i profili |
| `sway` | sessione/configurazione Sway | desktop Void |
| `vscode` | installazione/configurazione VS Code | Fedora, host Linux, Windows |
| `wsl` | bootstrap e configurazione WSL | WSL, Windows |
Esempi pratici:
```bash
ansible-playbook ansible/site.yml --limit nymph --tags dotfiles:desktop,sway --check --diff
ansible-playbook ansible/site.yml --limit deadalus-fedora --tags packages,vscode --check --diff
ansible-playbook ansible/site.yml --limit prometheus --tags services,dotfiles:server --check --diff
```
---
# Bootstrap di una nuova macchina
Una nuova macchina può essere inizializzata con i seguenti passaggi:
```bash
git clone <repo>
cd <repo-dir>
ansible-galaxy collection install -r ansible/collections/requirements.yml
ansible-playbook ansible/site.yml
```
Dopo l'esecuzione del playbook la macchina verra configurata secondo il profilo definito e i ruoli attualmente orchestrati.
Per il flusso mail desktop esiste inoltre uno script dedicato:
```bash
scripts/bootstrap_mail.sh
```
Lo script si occupa del bootstrap dei secret nel keyring, del primo sync con `mbsync` e dell'inizializzazione di `mu` usando la configurazione mail generata dai template.
Se modifichi questo script, valida almeno con:
```bash
sh -n scripts/bootstrap_mail.sh
shellcheck scripts/bootstrap_mail.sh
```
Una nuova macchina può essere inizializzata con i seguenti passaggi:
```bash
git clone <repo>
cd <repo-dir>
ansible-galaxy collection install -r ansible/collections/requirements.yml
ansible-playbook ansible/site.yml
```
Dopo l'esecuzione del playbook la macchina verra configurata secondo il profilo definito e i ruoli attualmente orchestrati.
Per il flusso mail desktop esiste inoltre uno script dedicato:
```bash
scripts/bootstrap_mail.sh
```
Lo script si occupa del bootstrap dei secret nel keyring, del primo sync con `mbsync` e dell'inizializzazione di `mu` usando la configurazione mail generata dai template.
Se modifichi questo script, valida almeno con:
```bash
sh -n scripts/bootstrap_mail.sh
shellcheck scripts/bootstrap_mail.sh
```
---
@@ -500,13 +499,13 @@ Questo consente di ricreare qualsiasi macchina partendo esclusivamente dal repos
# Roadmap
Possibili evoluzioni future:
- hardening sicurezza server
- configurazione backup
- testing automatico playbook
- integrazione CI
- supporto ad altre distribuzioni Linux
Possibili evoluzioni future:
- hardening sicurezza server
- configurazione backup
- testing automatico playbook
- integrazione CI
- supporto ad altre distribuzioni Linux
---

View File

@@ -50,42 +50,6 @@ common_dotfiles:
dest: .vimrc
mode: "0644"
- name: bat config
src: .config/bat/
src: .config/bat/.config/bat/
dest: .config/bat/
mode: preserve
ai_agents_npm_packages:
- name: "opencode-ai"
state: latest
- name: "@anthropic-ai/claude-code"
state: latest
- name: "@openai/codex"
state: latest
- name: "@google/gemini-cli"
state: latest
ai_agents_enabled: true
ai_agents_dotfiles:
- name: AI common config
src: .config/ai/
dest: .config/ai/
mode: preserve
- name: Gemini CLI config
src: .gemini/
dest: .gemini/
mode: preserve
- name: OpenCode config
src: .config/opencode/
dest: .config/opencode/
mode: preserve
- name: Claude Code memory
src: .claude/
dest: .claude/
mode: preserve
ai_agents_templates:
- name: Codex config
src: .codex/config.toml.j2
dest: .codex/config.toml
mode: "0644"

View File

@@ -9,6 +9,16 @@ desktop_default_session_env: xorg
desktop_restart_emptty_automatically: false
desktop_emptty_session_error_logging: disabled
desktop_ui_font_family: Noto Sans
desktop_ui_font_size: 10
desktop_fixed_font_family: Hack Nerd Font
desktop_sway_font_size: 10
desktop_alacritty_font_size: 12
desktop_emacs_font_size: 14
desktop_cursor_theme: Yaru
desktop_cursor_size: 24
desktop_icon_theme: Yaru-orange-dark
desktop_common_packages:
- brightnessctl
- dex
@@ -47,12 +57,18 @@ desktop_i3_packages:
- xss-lock
desktop_sway_packages:
- adw-gtk-theme
- flameshot
- grim
- kanshi
- qt5ct
- qt6ct
- slurp
- swayfx
- wl-clipboard
- xhost
- xdg-desktop-portal-wlr
- xorg-server-xwayland
profile_packages:
- alacritty
@@ -146,7 +162,9 @@ desktop_source_tools:
desktop_binary_tools: []
desktop_npm_packages: "{{ ai_agents_npm_packages + [] }}"
desktop_npm_packages:
- name: "opencode-ai"
state: latest
desktop_common_dotfiles:
- name: XDG autostart entries
@@ -181,6 +199,10 @@ desktop_common_dotfiles:
src: .config/yt-dlp/
dest: .config/yt-dlp/
mode: preserve
- name: OpenCode config
src: .config/opencode/
dest: .config/opencode/
mode: preserve
- name: MPV config
src: .config/mpv/
dest: .config/mpv/
@@ -225,14 +247,18 @@ desktop_common_dotfiles:
src: .local/bin/update-turnstile-env
dest: .local/bin/update-turnstile-env
mode: "0755"
- name: Gufw Sway wrapper
src: .local/bin/run-gufw
dest: .local/bin/run-gufw
mode: "0755"
- name: Udiskie password helper
src: .local/bin/udiskie-password
dest: .local/bin/udiskie-password
mode: "0755"
- name: Calibre database Flatpak wrapper
src: .local/bin/calibredb
dest: .local/bin/calibredb
mode: "0755"
- name: Desktop application overrides
src: .local/share/applications/
dest: .local/share/applications/
mode: preserve
- name: SSH config
src: .ssh/config
dest: .ssh/config
@@ -275,6 +301,10 @@ desktop_sway_dotfiles:
src: .config/i3/wallpapers/
dest: .config/sway/wallpapers/
mode: preserve
- name: Noctalia wallpaper library
src: Pictures/Wallpapers/
dest: Pictures/Wallpapers/
mode: preserve
- name: Sway session wrapper
src: .local/bin/start-sway-session
dest: .local/bin/start-sway-session
@@ -297,6 +327,8 @@ noctalia_bar_monitors:
noctalia_screen_overrides: []
noctalia_wallpaper: "{{ user_home }}/Pictures/Wallpapers/star-wars-trio.jpg"
desktop_flatpak_packages:
- be.alexandervanhee.gradia
- ch.protonmail.protonmail-bridge
@@ -308,4 +340,14 @@ desktop_flatpak_packages:
- org.telegram.desktop
desktop_flatpak_extensions:
- org.gtk.Gtk3theme.Yaru-Blue-dark//stable
- org.gtk.Gtk3theme.Yaru-Orange-dark//3.22
desktop_flatpak_global_filesystems:
- xdg-config/gtk-3.0:ro
- xdg-config/gtk-4.0:ro
- xdg-config/qt5ct:ro
- xdg-config/qt6ct:ro
desktop_flatpak_global_env:
- QT_QPA_PLATFORM=wayland
- QT_QPA_PLATFORMTHEME=qt6ct

View File

@@ -50,9 +50,6 @@ workstation_host_linux_packages_fedora:
- code
- firewall-config
- gnome-extensions-app
- gnome-shell-extension-appindicator
- gnome-shell-extension-just-perfection
- gnome-shell-extension-no-overview
- gnome-tweaks
- libreoffice
- meld
@@ -61,7 +58,6 @@ workstation_host_linux_packages_fedora:
- pinentry-gnome3
- podman
- podman-compose
- rclone
- yubikey-manager
workstation_flatpak_remote_name: flathub

View File

@@ -6,7 +6,6 @@ effective_username: "{{ server_username }}"
effective_user_group: "{{ server_user_group }}"
effective_user_home: "{{ server_user_home }}"
server_container_stack_dir: /opt/docker/server
ai_agents_enabled: false
profile_packages:
- avahi-daemon
@@ -93,14 +92,6 @@ server_directories:
owner: "1000"
group: "1000"
mode: "0755"
- path: /srv/nextcloud
owner: root
group: root
mode: "0755"
- path: /srv/nextcloud/data
owner: root
group: root
mode: "0755"
server_ufw_rules:
- rule: allow

View File

@@ -18,25 +18,18 @@ void_packages_base:
- fuse3
- gcc
- gdb
- gist
- github-cli
- gnome-keyring
- go
- gvfs
- hugo
- ImageMagick
- isync
- libsecret
- libtool
- linux-mainline
- lm_sensors
- man-pages-devel
- man-pages-posix
- msmtp
- mu4e
- network-manager-applet
- nodejs
- ntfs-3g
- pavucontrol
- pipewire
- pkg-config
@@ -49,7 +42,6 @@ void_packages_base:
- simple-scan
- socklog
- socklog-void
- speech-dispatcher
- syncthing
- system-config-printer
- tmux

View File

@@ -1,4 +1,6 @@
---
workstation_manage_opencode: true
workstation_npm_packages: "{{ ai_agents_npm_packages + [] }}"
workstation_npm_packages:
- name: "opencode-ai"
state: latest

View File

@@ -148,29 +148,3 @@ workstation_gnome_managed_settings:
- schema: org.gnome.TextEditor
key: wrap-text
value: "true"
- schema: org.gnome.desktop.background
key: picture-uri
value: "'file:///usr/share/backgrounds/gnome/lcd-rainbow-l.jxl'"
- schema: org.gnome.desktop.background
key: picture-uri-dark
value: "'file:///usr/share/backgrounds/gnome/lcd-rainbow-d.jxl'"
workstation_gnome_extension_dconf_settings:
- path: /org/gnome/shell/extensions/paperwm/
key: selection-border-radius-bottom
value: "15"
- path: /org/gnome/shell/extensions/paperwm/
key: selection-border-radius-top
value: "15"
- path: /org/gnome/shell/extensions/paperwm/
key: selection-border-size
value: "5"
- path: /org/gnome/shell/extensions/paperwm/
key: show-window-position-bar
value: "false"
- path: /org/gnome/shell/extensions/paperwm/
key: show-workspace-indicator
value: "false"
- path: /org/gnome/shell/extensions/paperwm/
key: window-gap
value: "10"

View File

@@ -2,10 +2,10 @@
hostname: nymph
desktop_sessions_enabled:
- i3
- sway
desktop_default_session: i3
desktop_default_session_env: xorg
desktop_default_session: sway
desktop_default_session_env: wayland
desktop_emptty_session_error_logging: rotate
host_xbps_repositories:
@@ -16,7 +16,6 @@ host_packages:
- cliphist
- grimshot
- nvidia
- linux-mainline-headers
- noctalia-shell
- power-profiles-daemon
- mesa-dri

View File

@@ -16,15 +16,6 @@
loop: "{{ xdg_user_directories | default([]) }}"
when: "'void' in group_names"
- name: Extract templates kit to Templates directory
tags: [dotfiles, dotfiles:common]
ansible.builtin.unarchive:
src: "{{ playbook_dir }}/../dotfiles/common/templates_kit.zip"
dest: "{{ effective_user_home }}/Templates"
owner: "{{ effective_username }}"
group: "{{ effective_user_group }}"
when: "'void' in group_names"
- name: Ensure SSH socket directory exists
tags: [dotfiles, dotfiles:common]
ansible.builtin.file:
@@ -42,41 +33,10 @@
owner: "{{ effective_username }}"
group: "{{ effective_user_group }}"
mode: "{{ item.mode }}"
loop: >-
{{
(common_dotfiles | default([]))
+ ((ai_agents_dotfiles | default([])) if (ai_agents_enabled | default(false)) else [])
}}
loop: "{{ common_dotfiles | default([]) }}"
loop_control:
label: "{{ item.dest }}"
- name: Ensure AI config directories exist
tags: [dotfiles, dotfiles:common]
ansible.builtin.file:
path: "{{ effective_user_home }}/{{ item }}"
state: directory
owner: "{{ effective_username }}"
group: "{{ effective_user_group }}"
mode: "0755"
loop:
- .codex
when:
- ai_agents_enabled | default(false)
- (ai_agents_templates | default([])) | length > 0
- name: Render AI agent templates
tags: [dotfiles, dotfiles:common]
ansible.builtin.template:
src: "{{ playbook_dir }}/../dotfiles/common/{{ item.src }}"
dest: "{{ effective_user_home }}/{{ item.dest }}"
owner: "{{ effective_username }}"
group: "{{ effective_user_group }}"
mode: "{{ item.mode }}"
loop: "{{ ai_agents_templates | default([]) }}"
loop_control:
label: "{{ item.dest }}"
when: ai_agents_enabled | default(false)
- name: Refresh bat cache
tags: [dotfiles, dotfiles:common]
ansible.builtin.command:

View File

@@ -18,10 +18,10 @@
loop:
- "{{ user_home }}/.config"
- "{{ user_home }}/.config/autostart"
- "{{ user_home }}/.config/dunst"
- "{{ user_home }}/.config/alacritty"
- "{{ user_home }}/.config/Thunar"
- "{{ user_home }}/.config/rofi"
- "{{ user_home }}/.local/share"
- "{{ user_home }}/.local/share/applications"
- "{{ user_home }}/.tmux"
- "{{ user_home }}/.tmux/bin"
- "{{ user_home }}/.tmux/plugins"
@@ -518,7 +518,7 @@
label: "{{ binary_tool.name }}"
- name: Install desktop npm packages
tags: [packages, npm]
tags: [packages]
community.general.npm:
name: "{{ item.name }}"
global: true

View File

@@ -10,6 +10,10 @@
loop:
- "{{ user_home }}/.config/sway"
- "{{ user_home }}/.config/kanshi"
- "{{ user_home }}/.config/qt5ct"
- "{{ user_home }}/.config/qt5ct/colors"
- "{{ user_home }}/.config/qt6ct"
- "{{ user_home }}/.config/qt6ct/colors"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Ensure Noctalia config directories exist
@@ -69,6 +73,26 @@
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Render qt5ct config
tags: [dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.template:
src: qt5ct.conf.j2
dest: "{{ user_home }}/.config/qt5ct/qt5ct.conf"
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Render qt6ct config
tags: [dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.template:
src: qt6ct.conf.j2
dest: "{{ user_home }}/.config/qt6ct/qt6ct.conf"
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Manage Noctalia shell plugins
tags: [dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.include_tasks: noctalia.yml
@@ -83,3 +107,37 @@
group: "{{ user_group }}"
mode: "0644"
when: "'sway' in (desktop_sessions_enabled | default([]))"
- name: Allow Flatpak apps to read shared theme configs
tags: [packages, dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.command:
argv:
- flatpak
- override
- --user
- "--filesystem={{ item }}"
become_user: "{{ username }}"
environment:
HOME: "{{ user_home }}"
changed_when: false
loop: "{{ desktop_flatpak_global_filesystems | default([]) }}"
when:
- "'sway' in (desktop_sessions_enabled | default([]))"
- (desktop_flatpak_packages | default([])) | length > 0
- name: Export global Flatpak environment for theme integration
tags: [packages, dotfiles, dotfiles:desktop, sway, noctalia]
ansible.builtin.command:
argv:
- flatpak
- override
- --user
- "--env={{ item }}"
become_user: "{{ username }}"
environment:
HOME: "{{ user_home }}"
changed_when: false
loop: "{{ desktop_flatpak_global_env | default([]) }}"
when:
- "'sway' in (desktop_sessions_enabled | default([]))"
- (desktop_flatpak_packages | default([])) | length > 0

View File

@@ -137,6 +137,22 @@
owner: "{{ username }}"
group: "{{ user_group }}"
loop:
- clipboard
- polkit-agent
- screenshot
- usb-drive-manager
- name: Ensure Noctalia cache directory exists
ansible.builtin.file:
path: "{{ user_home }}/.cache/noctalia"
state: directory
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0755"
- name: Deploy Noctalia wallpapers cache
ansible.builtin.template:
src: wallpapers.json.j2
dest: "{{ user_home }}/.cache/noctalia/wallpapers.json"
owner: "{{ username }}"
group: "{{ user_group }}"
mode: "0644"

View File

@@ -203,6 +203,18 @@
"middleClickCommand": "pwvucontrol || pavucontrol",
"textColor": "none"
},
{
"displayMode": "onhover",
"iconColor": "none",
"id": "Network",
"textColor": "none"
},
{
"displayMode": "onhover",
"iconColor": "none",
"id": "Bluetooth",
"textColor": "none"
},
{
"applyToAllMonitors": false,
"displayMode": "onhover",
@@ -561,15 +573,17 @@
{"enabled": true, "id": "alacritty"},
{"enabled": true, "id": "gtk"},
{"enabled": true, "id": "emacs"},
{"enabled": true, "id": "telegram"}
{"enabled": true, "id": "telegram"},
{"enabled": true, "id": "qt"},
{"enabled": true, "id": "sway"}
],
"enableUserTheming": false
},
"ui": {
"boxBorderEnabled": false,
"fontDefault": "Sans Serif",
"fontDefault": "{{ desktop_ui_font_family | default('Noto Sans') }}",
"fontDefaultScale": 1,
"fontFixed": "monospace",
"fontFixed": "{{ desktop_fixed_font_family | default('Hack Nerd Font') }}",
"fontFixedScale": 1,
"panelBackgroundOpacity": 0.93,
"panelsAttachedToBar": true,

View File

@@ -0,0 +1,6 @@
[Appearance]
color_scheme_path={{ user_home }}/.config/qt5ct/colors/noctalia.conf
custom_palette=true
icon_theme={{ desktop_icon_theme | default('Yaru-orange-dark') }}
standard_dialogs=default
style=Fusion

View File

@@ -0,0 +1,6 @@
[Appearance]
color_scheme_path={{ user_home }}/.config/qt6ct/colors/noctalia.conf
custom_palette=true
icon_theme={{ desktop_icon_theme | default('Yaru-orange-dark') }}
standard_dialogs=default
style=Fusion

View File

@@ -2,9 +2,9 @@ set $menu qs -c noctalia-shell ipc call launcher toggle
set $audio_panel qs -c noctalia-shell ipc call volume openPanel
set $locker qs -c noctalia-shell ipc call lockScreen lock
set $powermenu qs -c noctalia-shell ipc call sessionMenu toggle
set $screenshot_full qs -c noctalia-shell ipc call plugin:screenshot takeScreenshot output
set $screenshot_region qs -c noctalia-shell ipc call plugin:screenshot takeScreenshot region
set $screenshot_window qs -c noctalia-shell ipc call plugin:screenshot takeScreenshot window
set $screenshot_full sh -c 'QT_QPA_PLATFORM=wayland flameshot full --clipboard'
set $screenshot_region sh -c 'QT_QPA_PLATFORM=wayland flameshot gui'
set $screenshot_window sh -c 'QT_QPA_PLATFORM=wayland flameshot gui'
set $audio_raise qs -c noctalia-shell ipc call volume increase
set $audio_lower qs -c noctalia-shell ipc call volume decrease
set $audio_mute qs -c noctalia-shell ipc call volume muteOutput
@@ -22,8 +22,11 @@ exec pipewire
exec pipewire-pulse
exec wireplumber
exec kanshi
exec flameshot
exec udiskie --no-tray
exec wl-paste --watch cliphist store
exec qs -c noctalia-shell
bindsym $mod+c exec qs -c noctalia-shell ipc call launcher clipboard
bindsym $mod+Ctrl+v exec qs -c noctalia-shell ipc call plugin:clipboard toggle
bindsym $mod+Ctrl+Shift+v exec qs -c noctalia-shell ipc call plugin:clipboard wipe

View File

@@ -0,0 +1,18 @@
{
"defaultWallpaper": "/etc/xdg/quickshell/noctalia-shell/Assets/Wallpaper/noctalia.png",
"usedRandomWallpapers": {},
"wallpapers": {
"": {
"dark": "{{ noctalia_wallpaper }}",
"light": "{{ noctalia_wallpaper }}"
},
"DP-1": {
"dark": "{{ noctalia_wallpaper }}",
"light": "{{ noctalia_wallpaper }}"
},
"eDP-1": {
"dark": "{{ noctalia_wallpaper }}",
"light": "{{ noctalia_wallpaper }}"
}
}
}

View File

@@ -36,7 +36,7 @@
label: "{{ item.dest }}"
- name: Install workstation npm packages
tags: [packages, npm]
tags: [packages]
community.general.npm:
name: "{{ item.name }}"
global: true

View File

@@ -74,20 +74,6 @@
changed_when: true
when: item.stdout | trim != item.item.value
- name: Apply workstation GNOME extension dconf settings
tags: [gnome]
ansible.builtin.command:
argv:
- dconf
- write
- "{{ item.path }}{{ item.key }}"
- "{{ item.value }}"
become_user: "{{ username }}"
loop: "{{ workstation_gnome_extension_dconf_settings | default([]) }}"
loop_control:
label: "{{ item.path }}{{ item.key }}"
changed_when: true
- name: Check whether VS Code CLI is available on workstation host
tags: [packages, vscode]
ansible.builtin.command:

View File

@@ -36,25 +36,6 @@ services:
- web
- gitea
# Disabled: prometheus does not have enough resources to run Nextcloud AIO.
# nextcloud-aio-mastercontainer:
# image: ghcr.io/nextcloud-releases/all-in-one:latest
# container_name: nextcloud-aio-mastercontainer
# init: true
# restart: always
# ports:
# - "127.0.0.1:8080:8080"
# environment:
# APACHE_PORT: "11000"
# APACHE_IP_BINDING: "0.0.0.0"
# APACHE_ADDITIONAL_NETWORK: "server_web"
# NEXTCLOUD_DATADIR: "/srv/nextcloud/data"
# volumes:
# - "nextcloud_aio_mastercontainer:/mnt/docker-aio-config"
# - "/var/run/docker.sock:/var/run/docker.sock:ro"
# networks:
# - web
navidromedb:
image: postgres:13
container_name: navidromedb
@@ -106,11 +87,6 @@ services:
networks:
web:
name: server_web
external: false
gitea:
external: false
# volumes:
# nextcloud_aio_mastercontainer:
# name: nextcloud_aio_mastercontainer

View File

@@ -1,5 +0,0 @@
# Claude Code Global Context
Import the shared coding agent bootstrap context:
@~/.config/ai/bootstrap.md

View File

@@ -1,16 +0,0 @@
model = "gpt-5.5"
model_reasoning_effort = "medium"
model_instructions_file = "{{ effective_user_home }}/.config/ai/bootstrap.md"
[projects."/home/fscotto/AnsiblePlaybook"]
trust_level = "trusted"
[tui]
theme = "coldark-dark"
[tui.model_availability_nux]
"gpt-5.5" = 3
[features]
memories = true

View File

@@ -1,7 +0,0 @@
{
"$schema": "https://opencode.ai/config.json",
"instructions": [
"~/.config/ai/bootstrap.md",
"~/.config/ai/rules/safety.md"
]
}

View File

@@ -1,14 +0,0 @@
{
"security": {
"auth": {
"selectedType": "oauth-personal"
}
},
"context": {
"fileName": [
"~/.config/ai/bootstrap.md",
"~/.config/ai/rules/safety.md",
"~/.config/ai/AGENTS.md"
]
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -1,39 +0,0 @@
# Validate DBUS_SESSION_BUS_ADDRESS: a stale value (e.g. inherited from a
# dead X session) makes secret-tool, mbsync, msmtp fail with
# "Could not connect: No such file or directory".
# Fall back to ~/.dbus-session-bus-address (written by .xinitrc) or
# /run/user/$UID/bus, mirroring scripts/bootstrap_mail.sh.
_dbus_addr_socket_path() {
printf '%s' "${1#unix:path=}" | sed 's/,.*//'
}
_dbus_addr_is_live() {
case "$1" in
unix:path=*)
[ -S "$(_dbus_addr_socket_path "$1")" ]
;;
unix:abstract=*)
return 0
;;
*)
return 1
;;
esac
}
if ! _dbus_addr_is_live "${DBUS_SESSION_BUS_ADDRESS:-}"; then
unset DBUS_SESSION_BUS_ADDRESS
if [ -f "$HOME/.dbus-session-bus-address" ]; then
_saved=$(tr -d '\n' <"$HOME/.dbus-session-bus-address" 2>/dev/null)
if [ -n "$_saved" ] && _dbus_addr_is_live "$_saved"; then
export DBUS_SESSION_BUS_ADDRESS="$_saved"
fi
unset _saved
fi
if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] && [ -S "/run/user/$(id -u)/bus" ]; then
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
fi
fi
unset -f _dbus_addr_socket_path _dbus_addr_is_live

View File

@@ -12,7 +12,7 @@ ap() {
cmd+=(--tag "$1")
fi
printf '\033[0;36m+ %s\033[0m\n' "${cmd[*]}"
printf '+ %s\n' "${cmd[*]}"
"${cmd[@]}"
)
}

View File

@@ -1,3 +1,6 @@
[general]
import = ["~/.config/alacritty/themes/noctalia.toml"]
[window]
padding = { x = 8, y = 8 }
opacity = 1.0
@@ -13,33 +16,8 @@ multiplier = 3
[cursor]
style = { shape = "Beam", blinking = "Off" }
[colors.primary]
background = "#000000"
foreground = "#c8c8c8"
[colors.normal]
black = "#1f1f28"
red = "#c7162b"
green = "#4caf50"
yellow = "#e95420"
blue = "#4a90d9"
magenta = "#7e57c2"
cyan = "#6daeea"
white = "#eeeeee"
[colors.bright]
black = "#3a3a46"
red = "#ff5c5c"
green = "#7ad97a"
yellow = "#ff8f40"
blue = "#6daeea"
magenta = "#9575cd"
cyan = "#8bd6ff"
white = "#ffffff"
[keyboard]
bindings = [
{ key = "V", mods = "Control|Shift", action = "Paste" },
{ key = "C", mods = "Control|Shift", action = "Copy" },
{ key = "Return", mods = "Shift", chars = "\u001B\r" }
{ key = "C", mods = "Control|Shift", action = "Copy" }
]

View File

@@ -9,7 +9,7 @@ font pango:Liberation Mono 10
exec --no-startup-id dex --autostart --environment i3
exec --no-startup-id gnome-keyring-daemon --start --components=secrets
exec_always --no-startup-id setxkbmap -layout us -variant intl
exec_always --no-startup-id feh --bg-center ~/.config/i3/wallpapers/wallpaper-161664.jpg
exec_always --no-startup-id feh --bg-fill ~/.config/i3/wallpapers/void-minimalist2.png
exec_always --no-startup-id ~/.config/i3/scripts/setup-gtk-theme.sh
exec --no-startup-id /usr/libexec/xdg-desktop-portal

View File

@@ -1,6 +1,6 @@
#!/bin/sh
wallpaper="$HOME/.config/i3/wallpapers/maxresdefault.jpg"
wallpaper="$HOME/.config/i3/wallpapers/void-minimalist.png"
cached="$HOME/.cache/i3lock/wallpaper.png"
dims_cache="$HOME/.cache/i3lock/dims.txt"
dims=$(xdotool getdisplaygeometry | tr ' ' 'x')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -1,7 +1,7 @@
[Default Applications]
text/html=userapp-Firefox-91DVN3.desktop
x-scheme-handler/http=userapp-Firefox-91DVN3.desktop
x-scheme-handler/https=userapp-Firefox-91DVN3.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
application/pdf=com.github.xournalpp.xournalpp.desktop
@@ -164,13 +164,6 @@ text/x-readme=emacs.desktop
text/x-rst=emacs.desktop
text/x-tex=emacs.desktop
text/x-texinfo=emacs.desktop
x-scheme-handler/chrome=userapp-Firefox-91DVN3.desktop
application/x-extension-htm=userapp-Firefox-91DVN3.desktop
application/x-extension-html=userapp-Firefox-91DVN3.desktop
application/x-extension-shtml=userapp-Firefox-91DVN3.desktop
application/xhtml+xml=userapp-Firefox-91DVN3.desktop
application/x-extension-xhtml=userapp-Firefox-91DVN3.desktop
application/x-extension-xht=userapp-Firefox-91DVN3.desktop
[Added Associations]
application/json=emacs.desktop;
@@ -333,6 +326,3 @@ text/x-readme=emacs.desktop;
text/x-rst=emacs.desktop;
text/x-tex=emacs.desktop;
text/x-texinfo=emacs.desktop;
x-scheme-handler/http=userapp-Firefox-91DVN3.desktop;
x-scheme-handler/https=userapp-Firefox-91DVN3.desktop;
x-scheme-handler/chrome=userapp-Firefox-91DVN3.desktop;

View File

@@ -7,6 +7,10 @@
}
],
"states": {
"clipboard": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
},
"clipper": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
@@ -15,10 +19,6 @@
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
},
"screenshot": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"
},
"usb-drive-manager": {
"enabled": true,
"sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins"

View File

@@ -38,43 +38,7 @@
"fg": "mOnError"
}
},
"customColors": {
"Text": {
"bg": "#555555",
"separator": "#000000",
"fg": "#e9e4f0"
},
"Image": {
"bg": "#e0b7c9",
"separator": "#000000",
"fg": "#20161f"
},
"Link": {
"bg": "#c7a1d8",
"separator": "#000000",
"fg": "#1a151f"
},
"Code": {
"bg": "#a984c4",
"separator": "#000000",
"fg": "#f3edf7"
},
"Color": {
"bg": "#a984c4",
"separator": "#000000",
"fg": "#f3edf7"
},
"Emoji": {
"bg": "#e0b7c9",
"separator": "#000000",
"fg": "#20161f"
},
"File": {
"bg": "#e9899d",
"separator": "#000000",
"fg": "#1e1418"
}
},
"customColors": {},
"enableTodoIntegration": true,
"autoOpenPinnedPanel": false,
"pincardsEnabled": true,

View File

@@ -0,0 +1,7 @@
{
"$schema": "https://opencode.ai/config.json",
"instructions": [
"~/.config/opencode/bootstrap.md",
"~/.config/opencode/rules/safety.md"
]
}

View File

@@ -6,7 +6,7 @@ set $fallback_terminal st
include ~/.config/sway/host.conf
include ~/.config/sway/shell.conf
font pango:Liberation Mono 10
font pango:Hack Nerd Font 10
# Input and output defaults
seat seat0 xcursor_theme Yaru 24
@@ -166,9 +166,4 @@ mode "resize" {
bindsym $mod+r mode "resize"
client.focused #4a90d9 #4a90d9 #ffffff #4a90d9 #4a90d9
client.focused_inactive #3a3a46 #2b2b36 #eeeeee #3a3a46 #3a3a46
client.unfocused #2b2b36 #1f1f28 #bcbcbc #2b2b36 #2b2b36
client.urgent #c7162b #c7162b #ffffff #c7162b #c7162b
client.placeholder #1f1f28 #1f1f28 #bcbcbc #1f1f28 #1f1f28
client.background #1f1f28
include ~/.config/sway/noctalia

View File

@@ -45,7 +45,8 @@
'misc/rss
'misc/terminal
'misc/vcs
'misc/documents
'misc/pdf
'misc/epub
'misc/i3-config)
(message "...user configuration loaded")

View File

@@ -105,8 +105,8 @@
(define-key projectile-command-map (kbd "v") #'fscotto/project-multi-vterm)
(define-key projectile-command-map (kbd "V") nil)
(define-key projectile-command-map (kbd "x") #'fscotto/project-external-terminal)
(define-key projectile-command-map (kbd "a") #'fscotto/project-agent-dwim)
(define-key projectile-command-map (kbd "A") #'fscotto/project-agent-session)
(define-key projectile-command-map (kbd "a") #'fscotto/project-opencode-dwim)
(define-key projectile-command-map (kbd "A") #'fscotto/project-opencode-session)
(define-key projectile-command-map (kbd "g") #'fscotto/project-magit-status))
;;;; LSP

View File

@@ -1,16 +1,14 @@
;;; core-ui.el -*- lexical-binding: t; -*-
;; Load default theme
(use-package nordic-night-theme
:ensure t
:config
(load-theme 'nordic-night t))
;; Load generated Noctalia theme.
(add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory))
(load-theme 'noctalia t)
;; Setting default font
(set-frame-font "Liberation Mono 14" nil t)
(set-frame-font "Hack Nerd Font 14" nil t)
(add-to-list 'default-frame-alist
'(font . "Liberation Mono-14"))
'(font . "Hack Nerd Font-14"))
;; Remove toolbar
(tool-bar-mode -1)

View File

@@ -1,23 +1,6 @@
;;; json.el -*- lexical-binding: t -*-
(defun fscotto/json-maybe-start-lsp ()
"Start LSP for JSON buffers when lsp-mode is available."
(when (fboundp 'lsp-deferred)
(lsp-deferred)))
(use-package json-mode
:ensure t
:mode
(("\\.json\\'" . json-mode)
("\\.jsonc\\'" . json-mode))
:hook
(json-mode . fscotto/json-maybe-start-lsp))
(with-eval-after-load 'json-ts-mode
(add-hook 'json-ts-mode-hook #'fscotto/json-maybe-start-lsp))
(with-eval-after-load 'jsonc-mode
(add-hook 'jsonc-mode-hook #'fscotto/json-maybe-start-lsp))
:ensure t)
(provide 'json)

View File

@@ -1,5 +1,4 @@
(require 'seq)
(require 'subr-x)
;;functions to support syncing .elfeed between machines
;;makes sure elfeed reads index from disk before launching
(defvar fscotto/elfeed-initial-update-done nil
"Non-nil once Elfeed has triggered its first automatic update this session.")
@@ -129,24 +128,16 @@ Each entry is a cons cell of display string and session id."
"Return the latest saved OpenCode session id for the current project."
(cdr (car (fscotto/opencode-session-candidates (fscotto/project-root)))))
(defun fscotto/project-agent-dwim ()
"Choose an agent for the current project and launch it externally."
(defun fscotto/project-opencode-dwim ()
"Open the most useful OpenCode session for the current project.
Resume the latest saved session when available, otherwise create a new one."
(interactive)
(let ((agent (completing-read "Agent: " '("Claude" "Codex" "Gemini" "OpenCode") nil t)))
(pcase agent
("Claude"
(fscotto/launch-external-terminal '("claude" "--continue")))
("OpenCode"
(let ((session-id (fscotto/project-opencode-latest-session-id)))
(if session-id
(fscotto/launch-external-terminal (list "opencode" "--session" session-id)
(fscotto/project-root))
(fscotto/project-opencode))))
("Codex"
(fscotto/launch-external-terminal '("codex" "resume" "--last")))
("Gemini"
(fscotto/launch-external-terminal '("gemini" "--resume" "latest")
(fscotto/project-root))))))
(let ((session-id (fscotto/project-opencode-latest-session-id)))
(if session-id
(fscotto/launch-external-terminal (list "opencode" "--session" session-id)
(fscotto/project-root))
(fscotto/project-opencode))))
(defun fscotto/project-opencode-session ()
"Resume a saved OpenCode session for the current project."
@@ -160,78 +151,6 @@ Each entry is a cons cell of display string and session id."
(fscotto/launch-external-terminal (list "opencode" "--session" session-id)
project-directory))))
(defun fscotto/gemini-session-candidates (directory)
"Return Gemini session candidates for DIRECTORY.
Each entry is a cons cell of display string and session index.
Tries JSON output first, falls back to text parsing if unavailable."
(let* ((default-directory (file-name-as-directory directory))
(json-output (shell-command-to-string
"gemini --list-sessions --output-format json 2>/dev/null")))
(cond
((string-match "^{" json-output)
(ignore-errors
(require 'json)
(let* ((parsed (json-parse-string json-output))
(sessions (gethash "sessions" parsed)))
(when (vectorp sessions)
(seq-map-indexed
(lambda (s idx)
(let* ((idx-str (number-to-string (1+ idx)))
(msg (if (hash-table-p s)
(or (gethash "firstUserMessage" s) "Session")
"Session"))
(ts (and (hash-table-p s)
(ignore-errors (gethash "lastUpdated" s))
(when (stringp it) (string-trim it))))
(label (if ts (format "%s [%s]" msg ts) msg)))
(cons label idx-str)))
sessions)))))
(t
(let* ((output (shell-command-to-string "gemini --list-sessions"))
(lines (seq-filter (lambda (s) (string-match "\\S-" s))
(split-string output "\n" t)))
(data-lines (seq-drop lines 1))
(candidates nil))
(dolist (line data-lines)
(let ((trimmed (string-trim line)))
(when (string-match
(rx (group (one-or-more digit))
(one-or-more whitespace)
(group (one-or-more nonl)))
trimmed)
(push (cons (match-string 2 trimmed)
(match-string 1 trimmed))
candidates))))
(nreverse candidates))))))
(defun fscotto/project-gemini-session ()
"Choose and resume a Gemini session for the current project."
(interactive)
(let* ((project-directory (fscotto/project-root))
(candidates (fscotto/gemini-session-candidates project-directory)))
(unless candidates
(user-error "No Gemini sessions found for %s" project-directory))
(let* ((selection (completing-read "Gemini session: " candidates nil t))
(session-idx (cdr (assoc selection candidates))))
(fscotto/launch-external-terminal
(list "gemini" "--resume" session-idx)
project-directory))))
(defun fscotto/project-agent-session ()
"Choose an agent and resume a saved session for the current project."
(interactive)
(let ((agent (completing-read "Agent session: " '("Claude" "Codex" "Gemini" "OpenCode") nil t)))
(pcase agent
("Claude"
(fscotto/launch-external-terminal '("claude" "--resume")))
("OpenCode"
(fscotto/project-opencode-session))
("Codex"
(fscotto/launch-external-terminal '("codex" "resume")))
("Gemini"
(fscotto/project-gemini-session)))))
(defun fscotto/project-external-terminal ()
"Open the external terminal in project root."
(interactive)

View File

@@ -1,39 +0,0 @@
;;; documents.el -*- lexical-binding: t; -*-
(use-package pdf-tools
:ensure t
:config
(pdf-tools-install))
(use-package pdf-view
:config
(setq-default pdf-view-display-size 'fit-width)
(setq pdf-cache-org-imgparams t
pdf-view-use-smooth-scrolling t)
(setq pdf-annot-default-visible-properties t))
(with-eval-after-load 'pdf-view
(define-key pdf-view-mode-map (kbd "n") 'pdf-view-next-page)
(define-key pdf-view-mode-map (kbd "p") 'pdf-view-previous-page)
(define-key pdf-view-mode-map (kbd "q") 'pdf-view-close))
(use-package nov
:ensure t
:mode ("\\.epub\\'" . nov-mode))
(use-package calibre
:ensure t
:commands calibre-library
:config
(setq calibre-calibredb-executable
(or (executable-find "calibredb")
(let ((flatpak-wrapper (expand-file-name "~/.local/bin/calibredb")))
(when (file-executable-p flatpak-wrapper)
flatpak-wrapper))
"calibredb")
calibre-libraries
`(("Library" . ,(expand-file-name "~/Documents/Library")))))
(provide 'misc/documents)
;;; documents.el ends here

View File

@@ -0,0 +1,3 @@
(use-package nov
:ensure t
:mode ("\\.epub\\'" . nov-mode))

View File

@@ -0,0 +1,22 @@
;;; pdf.el -*- lexical-binding: t; -*-
(use-package pdf-tools
:ensure t
:config
(pdf-tools-install))
(use-package pdf-view
:config
(setq-default pdf-view-display-size 'fit-width)
(setq pdf-cache-org-imgparams t
pdf-view-use-smooth-scrolling t)
(setq pdf-annot-default-visible-properties t))
(with-eval-after-load 'pdf-view
(define-key pdf-view-mode-map (kbd "n") 'pdf-view-next-page)
(define-key pdf-view-mode-map (kbd "p") 'pdf-view-previous-page)
(define-key pdf-view-mode-map (kbd "q") 'pdf-view-close))
(provide 'misc/pdf)
;;; pdf.el ends here

View File

@@ -145,8 +145,8 @@
"C-c p t" "Test"
"C-c p v" "Open multi-vterm in project"
"C-c p x" "Open external term"
"C-c p a" "Choose agent"
"C-c p A" "Choose agent session"
"C-c p a" "OpenCode (dwim)"
"C-c p A" "Choose OpenCode session"
"C-c p e" "Edit project config"
"C-c p g" "Project Git status"
"C-c p 4" "Other Window"

View File

@@ -1,2 +0,0 @@
#!/bin/sh
exec flatpak run --command=calibredb com.calibre_ebook.calibre "$@"

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env sh
set -eu
if [ -z "${DISPLAY:-}" ]; then
printf 'Error: DISPLAY is not set; cannot launch gufw under Xwayland.\n' >&2
exit 1
fi
if ! command -v xhost >/dev/null 2>&1; then
printf 'Error: xhost is required to launch gufw from a Wayland session.\n' >&2
exit 1
fi
cleanup() {
xhost -si:localuser:root >/dev/null 2>&1 || true
}
trap cleanup EXIT INT TERM HUP
xhost si:localuser:root >/dev/null
exec gufw "$@"

View File

@@ -1,15 +1,13 @@
#!/bin/sh
THEME="Yaru-blue-dark"
ICONS="Yaru-blue-dark"
ICONS="Yaru-orange-dark"
CURSOR="Yaru"
FONT_UI="Liberation Sans 10"
FONT_UI="Noto Sans 10"
mkdir -p "$HOME/.config/gtk-3.0"
mkdir -p "$HOME/.config/gtk-4.0"
cat > "$HOME/.gtkrc-2.0" <<EOF
gtk-theme-name="$THEME"
gtk-icon-theme-name="$ICONS"
gtk-cursor-theme-name="$CURSOR"
gtk-font-name="$FONT_UI"
@@ -19,7 +17,6 @@ EOF
cat > "$HOME/.config/gtk-3.0/settings.ini" <<EOF
[Settings]
gtk-theme-name=$THEME
gtk-icon-theme-name=$ICONS
gtk-cursor-theme-name=$CURSOR
gtk-font-name=$FONT_UI
@@ -32,7 +29,6 @@ EOF
cat > "$HOME/.config/gtk-4.0/settings.ini" <<EOF
[Settings]
gtk-theme-name=$THEME
gtk-icon-theme-name=$ICONS
gtk-cursor-theme-name=$CURSOR
gtk-font-name=$FONT_UI
@@ -40,8 +36,8 @@ gtk-application-prefer-dark-theme=1
EOF
if command -v gsettings >/dev/null 2>&1; then
gsettings set org.gnome.desktop.interface gtk-theme "$THEME" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface icon-theme "$ICONS" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface cursor-theme "$CURSOR" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface font-name "$FONT_UI" >/dev/null 2>&1 || true
gsettings set org.gnome.desktop.interface color-scheme prefer-dark >/dev/null 2>&1 || true
fi

View File

@@ -0,0 +1,13 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Firewall Configuration
Comment=An easy way to configure your firewall
Keywords=gufw;security;firewall;network;
Categories=GNOME;GTK;Settings;Security;X-GNOME-Settings-Panel;X-GNOME-SystemSettings;X-Unity-Settings-Panel;X-XFCE-SettingsDialog;X-XFCE-SystemSettings;
Exec=/home/fscotto/.local/bin/run-gufw
Icon=gufw
Terminal=false
X-GNOME-Settings-Panel=gufw
X-Unity-Settings-Panel=gufw
X-Ubuntu-Gettext-Domain=gufw

View File

@@ -1,8 +1,4 @@
Host vps
IdentityFile ~/.ssh/id_rsa_vps
Host *
IdentityFile ~/.ssh/id_ed25519
ControlMaster auto
ControlPath ~/.local/state/ssh/sockets/%r@%h-%p
ControlPersist 600

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -1,4 +1,6 @@
export LIBVA_DRIVER_NAME=iHD
export QT_QPA_PLATFORM=wayland
export QT_QPA_PLATFORMTHEME=qt6ct
export SWAY_UNSUPPORTED_GPU=1
export WLR_DRM_DEVICES=/dev/dri/card0:/dev/dri/card1
export WLR_NO_HARDWARE_CURSORS=1

View File

@@ -198,20 +198,8 @@ parse_secret_lookup_args() {
resolve_dbus_session_bus_address() {
if [ -n "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
case "$DBUS_SESSION_BUS_ADDRESS" in
unix:path=*)
_path=${DBUS_SESSION_BUS_ADDRESS#unix:path=}
_path=${_path%%,*}
if [ -S "$_path" ]; then
printf '%s\n' "$DBUS_SESSION_BUS_ADDRESS"
return 0
fi
;;
unix:abstract=*)
printf '%s\n' "$DBUS_SESSION_BUS_ADDRESS"
return 0
;;
esac
printf '%s\n' "$DBUS_SESSION_BUS_ADDRESS"
return 0
fi
if [ -f "$HOME/.dbus-session-bus-address" ]; then

View File

@@ -0,0 +1,242 @@
#!/usr/bin/env sh
set -eu
APPLY=0
AGGRESSIVE=0
SAFE_PACKAGES="
arandr
autorandr
feh
i3
i3blocks
i3blocks-blocklets
i3lock-color
i3status
scrot
setxkbmap
volumeicon
xclip
xkbutils
xorg-fonts
xorg-minimal
xss-lock
"
AGGRESSIVE_PACKAGES="
dunst
rofi
blueman
network-manager-applet
xfce-polkit
xfce4-clipman-plugin
xfce4-screenshooter
"
SAFE_PATHS="
$HOME/.config/i3
$HOME/.config/i3blocks
$HOME/.config/autorandr
$HOME/.xinitrc
"
AGGRESSIVE_PATHS="
$HOME/.config/dunst
$HOME/.config/rofi
"
usage() {
cat <<'EOF'
Usage: cleanup_i3_after_sway_migration.sh [--apply] [--aggressive]
One-shot cleanup for removing i3/X11-only packages and dotfiles after a host
has already migrated to SwayFX + Noctalia.
Options:
--apply perform the cleanup for real
--aggressive also remove extra desktop apps/configs that were mainly useful
in the old i3 setup (dunst, rofi, blueman, etc.)
-h, --help show this help
Default mode is dry-run.
EOF
}
have_command() {
command -v "$1" >/dev/null 2>&1
}
require_sway_noctalia() {
if [ ! -f "$HOME/.config/sway/config" ]; then
printf 'Error: Sway config not found at %s\n' "$HOME/.config/sway/config" >&2
exit 1
fi
if [ ! -f "$HOME/.config/noctalia/settings.json" ]; then
printf 'Error: Noctalia settings not found at %s\n' "$HOME/.config/noctalia/settings.json" >&2
exit 1
fi
}
append_lines() {
src_lines=$1
dst_var=$2
for line in $src_lines; do
line=$(printf '%s' "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$line" ] || continue
case "$dst_var" in
PACKAGES)
PACKAGES="$PACKAGES $line"
;;
PATHS)
PATHS="$PATHS $line"
;;
*)
printf 'Error: unsupported destination list: %s\n' "$dst_var" >&2
exit 1
;;
esac
done
}
filter_installed_packages() {
packages=$1
installed=''
for pkg in $packages; do
pkg=$(printf '%s' "$pkg" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$pkg" ] || continue
if xbps-query -s "$pkg" >/dev/null 2>&1; then
installed="$installed $pkg"
fi
done
printf '%s' "$installed"
}
filter_existing_paths() {
paths=$1
existing=''
for path in $paths; do
path=$(printf '%s' "$path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$path" ] || continue
if [ -e "$path" ] || [ -L "$path" ]; then
existing="$existing $path"
fi
done
printf '%s' "$existing"
}
print_section() {
title=$1
items=$2
printf '%s\n' "$title"
if [ -z "$items" ]; then
printf ' (none)\n'
return
fi
for item in $items; do
item=$(printf '%s' "$item" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$item" ] || continue
printf ' - %s\n' "$item"
done
}
confirm_apply() {
printf 'Proceed with i3 cleanup? [y/N] '
IFS= read -r answer
case "$answer" in
y|Y|yes|YES)
;;
*)
printf 'Aborted.\n'
exit 0
;;
esac
}
run_remove_packages() {
packages=$1
[ -n "$packages" ] || return 0
if [ "$(id -u)" -eq 0 ]; then
xbps-remove -R $packages
elif have_command sudo; then
sudo xbps-remove -R $packages
else
printf 'Error: package removal requires root and sudo was not found.\n' >&2
exit 1
fi
}
run_remove_paths() {
paths=$1
[ -n "$paths" ] || return 0
for path in $paths; do
path=$(printf '%s' "$path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$path" ] || continue
rm -rf "$path"
done
}
while [ $# -gt 0 ]; do
case "$1" in
--apply)
APPLY=1
;;
--aggressive)
AGGRESSIVE=1
;;
-h|--help)
usage
exit 0
;;
*)
printf 'Error: unknown argument: %s\n\n' "$1" >&2
usage >&2
exit 1
;;
esac
shift
done
require_sway_noctalia
PACKAGES=''
PATHS=''
append_lines "$SAFE_PACKAGES" PACKAGES
append_lines "$SAFE_PATHS" PATHS
if [ "$AGGRESSIVE" -eq 1 ]; then
append_lines "$AGGRESSIVE_PACKAGES" PACKAGES
append_lines "$AGGRESSIVE_PATHS" PATHS
fi
INSTALLED_PACKAGES=$(filter_installed_packages "$PACKAGES")
EXISTING_PATHS=$(filter_existing_paths "$PATHS")
printf 'Mode: %s\n' "$( [ "$APPLY" -eq 1 ] && printf 'apply' || printf 'dry-run' )"
printf 'Aggressive cleanup: %s\n\n' "$( [ "$AGGRESSIVE" -eq 1 ] && printf 'yes' || printf 'no' )"
print_section 'Packages to remove:' "$INSTALLED_PACKAGES"
printf '\n'
print_section 'Paths to remove:' "$EXISTING_PATHS"
if [ "$APPLY" -ne 1 ]; then
printf '\nDry-run only. Re-run with --apply to perform the cleanup.\n'
exit 0
fi
confirm_apply
run_remove_packages "$INSTALLED_PACKAGES"
run_remove_paths "$EXISTING_PATHS"
printf '\nCleanup complete.\n'

View File

@@ -1,73 +0,0 @@
#!/usr/bin/env sh
set -eu
PACKAGES="
swayfx
kanshi
grim
grimshot
slurp
wl-clipboard
xdg-desktop-portal-wlr
cliphist
noctalia-shell
"
USER_PATHS="
$HOME/.config/sway
$HOME/.config/kanshi
$HOME/.config/noctalia
$HOME/.local/share/noctalia-plugins
$HOME/.local/bin/start-sway-session
"
SYSTEM_FILES="
/etc/emptty/wayland-sessions/Sway.desktop
/etc/xbps.d/noctalia.conf
"
check_host() {
if [ "$(hostname)" != "nymph" ]; then
printf 'Error: questo script è destinato solo a nymph (hostname attuale: %s)\n' "$(hostname)" >&2
exit 1
fi
}
remove_packages() {
printf 'Rimozione pacchetti swayfx+noctalia...\n'
# shellcheck disable=SC2086
sudo xbps-remove -Ry $PACKAGES
printf 'Rimozione dipendenze orfane...\n'
sudo xbps-remove -o
}
remove_user_configs() {
printf 'Rimozione configurazioni utente...\n'
for path in $USER_PATHS; do
if [ -e "$path" ]; then
rm -rf "$path"
printf ' rimosso: %s\n' "$path"
fi
done
}
remove_system_files() {
printf 'Rimozione file di sistema...\n'
for file in $SYSTEM_FILES; do
if [ -e "$file" ]; then
sudo rm -f "$file"
printf ' rimosso: %s\n' "$file"
fi
done
}
main() {
check_host
remove_packages
remove_user_configs
remove_system_files
printf 'Cleanup completato.\n'
}
main "$@"