diff --git a/ansible/inventory/group_vars/desktop.yml b/ansible/inventory/group_vars/desktop.yml index 2f970d8..90c2766 100644 --- a/ansible/inventory/group_vars/desktop.yml +++ b/ansible/inventory/group_vars/desktop.yml @@ -1,6 +1,4 @@ --- -desktop_protonmail_bridge_cert_path: ~/.var/app/ch.protonmail.protonmail-bridge/config/protonmail/bridge-v3/cert.pem - desktop_environment: minimal desktop_allow_display_manager_switch: false diff --git a/ansible/inventory/group_vars/desktop_cinnamon.yml b/ansible/inventory/group_vars/desktop_cinnamon.yml index 6feacc3..7e2ac7b 100644 --- a/ansible/inventory/group_vars/desktop_cinnamon.yml +++ b/ansible/inventory/group_vars/desktop_cinnamon.yml @@ -7,6 +7,13 @@ cinnamon_theme_icons: Mint-Y-Aqua cinnamon_font_ui: Sans 10 cinnamon_font_monospace: Monospace 10 +# WM-agnostic desktop dotfiles from desktop_common_dotfiles that do NOT apply to +# Cinnamon: the autostart entry is the (removed) Protonmail mail bridge, and the +# GTK theme script conflicts with Cinnamon's own dconf-managed theming. +cinnamon_desktop_dotfiles_exclude: + - XDG autostart entries + - GTK theme setup script + cinnamon_dconf_settings: - key: /org/cinnamon/desktop/interface/gtk-theme value: "'{{ cinnamon_theme_gtk }}'" diff --git a/ansible/inventory/group_vars/platform_mint.yml b/ansible/inventory/group_vars/platform_mint.yml index 80afea6..f2d662a 100644 --- a/ansible/inventory/group_vars/platform_mint.yml +++ b/ansible/inventory/group_vars/platform_mint.yml @@ -4,6 +4,11 @@ platform_family: debian platform_package_manager: apt platform_service_manager: systemd +# syncthing runs per-user via the packaged system unit template +# (Debian/Mint ship syncthing@.service, parametrised by username). +enabled_services: + - "syncthing@{{ username }}.service" + mint_manage_flatpak: true mint_flatpak_remote_name: flathub mint_flatpak_remote_url: https://dl.flathub.org/repo/flathub.flatpakrepo @@ -39,13 +44,20 @@ mint_desktop_common_packages: - firefox - fonts-liberation - fonts-noto-color-emoji + - git-delta - gnome-keyring + - libfreetype-dev - libsecret-tools + - libx11-dev - mpv - pinentry-gnome3 + - pinentry-gtk2 - rclone + - syncthing - thunderbird + - tmux - xdg-user-dirs + - yt-dlp mint_cinnamon_packages: - cinnamon @@ -62,4 +74,19 @@ mint_personal_workstation_packages: - pdfarranger - vim -mint_flatpak_packages: [] +mint_flatpak_packages: + - ch.protonmail.protonmail-bridge + - com.calibre_ebook.calibre + - com.spotify.Client + - org.telegram.desktop + +# Nerd Fonts referenced by the desktop configs deployed on Mint (fontconfig +# symbols, Emacs UI/vterm). Debian has no equivalent of Void's nerd-fonts-ttf +# package, so they are fetched from the upstream ryanoasis/nerd-fonts release. +mint_nerd_fonts_version: v3.3.0 +mint_nerd_fonts: + - Hack + # Archive is named UbuntuSans; it ships the "UbuntuSansMono Nerd Font" faces + # referenced by the Emacs UI config. + - UbuntuSans + - NerdFontsSymbolsOnly diff --git a/ansible/inventory/group_vars/void.yml b/ansible/inventory/group_vars/void.yml index 23bfe14..848d2d0 100644 --- a/ansible/inventory/group_vars/void.yml +++ b/ansible/inventory/group_vars/void.yml @@ -23,7 +23,6 @@ void_packages_base: - go - hugo - ImageMagick - - isync - libtool - linux - linux-headers @@ -33,8 +32,6 @@ void_packages_base: - lm_sensors - man-pages-devel - man-pages-posix - - msmtp - - mu4e - nodejs - ntfs-3g - pipewire diff --git a/ansible/inventory/host_vars/ikaros.yml b/ansible/inventory/host_vars/ikaros.yml index f119efa..326f0ef 100644 --- a/ansible/inventory/host_vars/ikaros.yml +++ b/ansible/inventory/host_vars/ikaros.yml @@ -2,12 +2,10 @@ hostname: ikaros host_packages: - - openssh - - mesa-dri - - vulkan-loader - - mesa-vulkan-radeon - - mesa-vaapi - - xf86-video-amdgpu + - openssh-client + - openssh-server + - mesa-vulkan-drivers + - xserver-xorg-video-amdgpu host_ufw_rules: - rule: allow @@ -27,4 +25,4 @@ host_sshd_allow_users: host_authorized_ssh_keys: "{{ vault_ikaros_authorized_ssh_keys | default([]) }}" host_enabled_services: - - sshd + - ssh diff --git a/ansible/inventory/hosts.yml b/ansible/inventory/hosts.yml index 855e6d3..befcd25 100644 --- a/ansible/inventory/hosts.yml +++ b/ansible/inventory/hosts.yml @@ -2,14 +2,12 @@ all: children: platform_void: + hosts: {} + + platform_mint: hosts: ikaros: ansible_connection: local - nymph: - ansible_connection: local - - platform_mint: - hosts: {} platform_freebsd: hosts: {} @@ -40,21 +38,15 @@ all: ansible_connection: local desktop_sway: - hosts: - ikaros: - ansible_connection: local - nymph: - ansible_connection: local + hosts: {} desktop_hyprland: - hosts: - ikaros: - ansible_connection: local - nymph: - ansible_connection: local + hosts: {} desktop_cinnamon: - hosts: {} + hosts: + ikaros: + ansible_connection: local ubuntu: children: diff --git a/ansible/roles/profile_desktop_cinnamon/tasks/main.yml b/ansible/roles/profile_desktop_cinnamon/tasks/main.yml index affe04b..66cae08 100644 --- a/ansible/roles/profile_desktop_cinnamon/tasks/main.yml +++ b/ansible/roles/profile_desktop_cinnamon/tasks/main.yml @@ -11,6 +11,12 @@ - "{{ user_home }}/.config" - "{{ user_home }}/.local" - "{{ user_home }}/.local/share" + - "{{ user_home }}/.local/bin" + - "{{ user_home }}/.local/state" + - "{{ user_home }}/.bashrc.d" + - "{{ user_home }}/.tmux" + - "{{ user_home }}/.tmux/bin" + - "{{ user_home }}/.tmux/plugins" - name: Apply Cinnamon dconf settings tags: [cinnamon] @@ -25,3 +31,197 @@ loop: "{{ cinnamon_dconf_settings | default([]) }}" loop_control: label: "{{ item.key }}" + +- name: Ensure Emacs config directory exists + tags: [dotfiles, dotfiles:desktop, emacs] + ansible.builtin.file: + path: "{{ user_home }}/.emacs.d" + state: directory + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "0755" + +- name: Ensure GnuPG directory exists + tags: [dotfiles, dotfiles:desktop, git] + ansible.builtin.file: + path: "{{ user_home }}/.gnupg" + state: directory + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "0700" + +- name: Ensure private user directories exist + tags: [dotfiles, dotfiles:desktop] + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "0700" + loop: + - "{{ user_home }}/.ssh" + - "{{ user_home }}/.local/state/ssh/sockets" + +- name: Copy Emacs desktop dotfiles + tags: [dotfiles, dotfiles:desktop, emacs] + ansible.builtin.copy: + src: "{{ playbook_dir }}/../dotfiles/desktop/{{ item.src }}" + dest: "{{ user_home }}/{{ item.dest }}" + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "{{ item.mode }}" + loop: "{{ desktop_emacs_dotfiles | default([]) }}" + loop_control: + label: "{{ item.dest }}" + +- name: Copy WM-agnostic common desktop dotfiles + tags: [dotfiles, dotfiles:desktop] + ansible.builtin.copy: + src: "{{ playbook_dir }}/../dotfiles/desktop/{{ item.src }}" + dest: "{{ user_home }}/{{ item.dest }}" + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "{{ item.mode }}" + loop: >- + {{ + desktop_common_dotfiles + | default([]) + | rejectattr('name', 'in', cinnamon_desktop_dotfiles_exclude | default([])) + | list + }} + loop_control: + label: "{{ item.dest }}" + +- name: Copy gpg-agent configuration + tags: [dotfiles, dotfiles:desktop, git] + ansible.builtin.copy: + src: "{{ playbook_dir }}/../dotfiles/desktop/.gnupg/gpg-agent.conf" + dest: "{{ user_home }}/.gnupg/gpg-agent.conf" + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "0600" + +- name: Render git configuration with private values + tags: [dotfiles, dotfiles:desktop, git] + ansible.builtin.template: + src: desktop/.gitconfig.j2 + dest: "{{ user_home }}/.gitconfig" + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "0644" + +- name: Bootstrap tmux plugin manager checkout + tags: [dotfiles, dotfiles:desktop, tmux] + ansible.builtin.git: + repo: https://github.com/tmux-plugins/tpm + dest: "{{ user_home }}/.tmux/plugins/tpm" + version: master + update: true + become_user: "{{ username }}" + environment: + HOME: "{{ user_home }}" + +- name: Install tmux plugins through TPM + tags: [dotfiles, dotfiles:desktop, tmux] + ansible.builtin.command: + cmd: "{{ user_home }}/.tmux/plugins/tpm/bin/install_plugins" + become_user: "{{ username }}" + environment: + HOME: "{{ user_home }}" + register: cinnamon_tmux_plugin_install + changed_when: >- + (cinnamon_tmux_plugin_install.stdout | default('')) is search('download success') or + (cinnamon_tmux_plugin_install.stderr | default('')) is search('download success') + +- name: Install desktop npm packages + tags: [packages, npm] + community.general.npm: + name: "{{ item.name }}" + global: true + state: "{{ item.state | default('present') }}" + become: true + loop: "{{ desktop_npm_packages | default([]) }}" + when: desktop_npm_packages | length > 0 + loop_control: + label: "{{ item.name }}" + +- name: Ensure /usr/src is writable for source builds + tags: [packages] + ansible.builtin.file: + path: /usr/src + state: directory + owner: "{{ username }}" + group: "{{ user_group }}" + mode: "0755" + +- name: Build and install the gf debugger frontend from source + tags: [packages] + ansible.builtin.include_tasks: + file: "{{ role_path }}/../profile_desktop_common/tasks/source_tool.yml" + apply: + tags: [packages] + loop: >- + {{ + desktop_source_tools + | default([]) + | selectattr('name', 'equalto', 'gf') + | list + }} + loop_control: + loop_var: source_tool + label: "{{ source_tool.name }}" + +- name: Ensure Nerd Fonts base directory exists + tags: [packages, fonts] + ansible.builtin.file: + path: /usr/local/share/fonts/nerd-fonts + state: directory + owner: root + group: root + mode: "0755" + become: true + +- name: Ensure per-font Nerd Fonts directories exist + tags: [packages, fonts] + ansible.builtin.file: + path: "/usr/local/share/fonts/nerd-fonts/{{ item }}" + state: directory + owner: root + group: root + mode: "0755" + become: true + loop: "{{ mint_nerd_fonts | default([]) }}" + +- name: Download Nerd Font archives + tags: [packages, fonts] + ansible.builtin.get_url: + url: "https://github.com/ryanoasis/nerd-fonts/releases/download/{{ mint_nerd_fonts_version }}/{{ item }}.zip" + dest: "/usr/local/share/fonts/nerd-fonts/{{ item }}.zip" + owner: root + group: root + mode: "0644" + become: true + loop: "{{ mint_nerd_fonts | default([]) }}" + loop_control: + label: "{{ item }}" + +- name: Extract Nerd Font archives + tags: [packages, fonts] + ansible.builtin.unarchive: + src: "/usr/local/share/fonts/nerd-fonts/{{ item }}.zip" + dest: "/usr/local/share/fonts/nerd-fonts/{{ item }}" + remote_src: true + owner: root + group: root + become: true + loop: "{{ mint_nerd_fonts | default([]) }}" + loop_control: + label: "{{ item }}" + register: cinnamon_nerd_fonts_extract + +- name: Refresh system font cache after installing Nerd Fonts + tags: [packages, fonts] + ansible.builtin.command: fc-cache -f + become: true + changed_when: false + when: cinnamon_nerd_fonts_extract is changed diff --git a/ansible/roles/profile_desktop_common/tasks/main.yml b/ansible/roles/profile_desktop_common/tasks/main.yml index 07db78f..ced6143 100644 --- a/ansible/roles/profile_desktop_common/tasks/main.yml +++ b/ansible/roles/profile_desktop_common/tasks/main.yml @@ -318,29 +318,14 @@ loop_control: label: "{{ item.dest }}" -- name: Render desktop templates with private values - tags: [dotfiles, dotfiles:desktop] +- name: Render git configuration with private values + tags: [dotfiles, dotfiles:desktop, git] ansible.builtin.template: - src: "{{ item.src }}" - dest: "{{ user_home }}/{{ item.dest }}" + src: desktop/.gitconfig.j2 + dest: "{{ user_home }}/.gitconfig" owner: "{{ username }}" group: "{{ user_group }}" - mode: "{{ item.mode }}" - loop: - - src: desktop/.gitconfig.j2 - dest: .gitconfig - mode: "0644" - - src: desktop/.mbsyncrc.j2 - dest: .mbsyncrc - mode: "0600" - - src: desktop/.msmtprc.j2 - dest: .msmtprc - mode: "0600" - - src: desktop/email.el.j2 - dest: .emacs.d/lisp/misc/email.el - mode: "0644" - loop_control: - label: "{{ item.dest }}" + mode: "0644" - name: Define managed tmux plugin directories tags: [dotfiles, dotfiles:desktop, tmux] @@ -451,19 +436,6 @@ - path: /usr/src mode: "0755" -- name: Ensure maildir directories exist - tags: [dotfiles, dotfiles:desktop] - ansible.builtin.file: - path: "{{ item }}" - state: directory - owner: "{{ username }}" - group: "{{ user_group }}" - mode: "0700" - loop: - - "{{ user_home }}/Maildir" - - "{{ user_home }}/Maildir/iCloudAccount" - - "{{ user_home }}/Maildir/ProtonMailAccount" - - name: Make Qt apps follow the GTK theme tags: [theme] ansible.builtin.copy: diff --git a/ansible/templates/desktop/.mbsyncrc.j2 b/ansible/templates/desktop/.mbsyncrc.j2 deleted file mode 100644 index 7746945..0000000 --- a/ansible/templates/desktop/.mbsyncrc.j2 +++ /dev/null @@ -1,47 +0,0 @@ -##################### iCloud Account ################################## -IMAPStore iCloud-remote - Host imap.mail.me.com - Port 993 - User {{ vault_icloud_email }} - PassCmd "secret-tool lookup icloud-mail icloud" - AuthMechs * - TLSType IMAPS - TLSVersions +1.2 +1.3 - PipelineDepth 1 - -MaildirStore iCloud-local - Path ~/Maildir/iCloudAccount/ - Inbox ~/Maildir/iCloudAccount/INBOX - SubFolders Verbatim - -Channel iCloud - Far :iCloud-remote: - Near :iCloud-local: - Patterns * - Create Both - Expunge Both - SyncState * - -##################### Protonmail Account ################################## -IMAPStore protonmail-remote - Host 127.0.0.1 - Port 1143 - User {{ vault_protonmail_email }} - PassCmd "secret-tool lookup protonmail-bridge protonmail" - AuthMechs * - TLSType STARTTLS - PipelineDepth 1 - CertificateFile {{ desktop_protonmail_bridge_cert_path }} - -MaildirStore protonmail-local - Path ~/Maildir/ProtonMailAccount/ - Inbox ~/Maildir/ProtonMailAccount/INBOX - SubFolders Verbatim - -Channel Protonmail - Far :protonmail-remote: - Near :protonmail-local: - Patterns * - Create Both - Expunge Both - SyncState * diff --git a/ansible/templates/desktop/.msmtprc.j2 b/ansible/templates/desktop/.msmtprc.j2 deleted file mode 100644 index ee9b357..0000000 --- a/ansible/templates/desktop/.msmtprc.j2 +++ /dev/null @@ -1,51 +0,0 @@ -# Set default values for all following accounts. -defaults - -# Always use TLS -tls on - -# Set a list of trusted CAs for TLS. The default is to use system settings, -# but you can select your own file. -tls_trust_file /etc/ssl/certs/ca-certificates.crt -logfile ~/.cache/msmtp.log - -# Account iCloud -account icloud - -# Host name of the SMTP server -host smtp.mail.me.com - -# Use the mail submission port 587 instead of the SMTP port 25 -port 587 - -# Envelop-from address -from {{ vault_icloud_email }} - -# Authentication. The password is given using one of five methods -auth on -user {{ vault_icloud_email }} -passwordeval "secret-tool lookup icloud-mail icloud" - -# Account Protonmail -account protonmail - -# Hostname of the Protonmail bridge -host 127.0.0.1 - -# Port of the Protonmail bridge -port 1025 - -# Envelop-from address -from {{ vault_protonmail_email }} - -# Security -tls on -tls_trust_file {{ desktop_protonmail_bridge_cert_path }} - -# Authentication -auth on -user {{ vault_protonmail_email }} -passwordeval "secret-tool lookup protonmail-bridge protonmail" - -# Set a default account -account default : icloud diff --git a/ansible/templates/desktop/email.el.j2 b/ansible/templates/desktop/email.el.j2 deleted file mode 100644 index 4415acf..0000000 --- a/ansible/templates/desktop/email.el.j2 +++ /dev/null @@ -1,53 +0,0 @@ -;;; email.el -*- - -(use-package mu4e - :ensure nil - :load-path "/usr/share/emacs/site-lisp/mu4e/" - :defer 20 ; Wait until 20 seconds after startup - :config - ;; This is set to 't' to avoid mail syncing issues when using mbsync - (setq mu4e-change-filenames-when-moving t) - - ;; Refresh mail using isync every 10 minutes - (setq mu4e-update-interval (* 10 60)) - (setq mu4e-get-mail-command "~/.emacs.d/scripts/email_sync.sh") - (setq mu4e-maildir "~/Maildir") - - ;; Configure email accounts - (setq mu4e-contexts - (list - ;; Protonmail Account - (make-mu4e-context - :name "Protonmail" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/ProtonMailAccount" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "{{ vault_protonmail_email }}") - (user-full-name . "{{ vault_personal_full_name }}") - (mu4e-drafts-folder . "/ProtonMailAccount/Drafts") - (mu4e-sent-folder . "/ProtonMailAccount/Sent") - (mu4e-refile-folder . "/ProtonMailAccount/All Mail") - (mu4e-trash-folder . "/ProtonMailAccount/Trash"))) - - ;; iCloud Account - (make-mu4e-context - :name "iCloud Mail" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/iCloudAccount" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "{{ vault_icloud_email }}") - (user-full-name . "{{ vault_personal_full_name }}") - (mu4e-drafts-folder . "/iCloudAccount/Drafts") - (mu4e-sent-folder . "/iCloudAccount/Sent Messages") - (mu4e-refile-folder . "/iCloudAccount/INBOX") - (mu4e-trash-folder . "/iCloudAccount/Junk"))))) - - (setq sendmail-program "/usr/bin/msmtp" - mail-user-agent 'mu4e-user-agent - read-mail-command 'mu4e - send-mail-function 'sendmail-send-it - message-sendmail-f-is-evil t - message-sendmail-extra-arguments '("--read-envelope-from") - message-send-mail-function 'message-send-mail-with-sendmail)) diff --git a/dotfiles/desktop/.emacs.d/init.el b/dotfiles/desktop/.emacs.d/init.el index 8f89275..07e93df 100644 --- a/dotfiles/desktop/.emacs.d/init.el +++ b/dotfiles/desktop/.emacs.d/init.el @@ -42,7 +42,6 @@ 'misc/doom-modeline 'misc/which-key 'misc/gptel - 'misc/email 'misc/rss 'misc/terminal 'misc/vcs diff --git a/dotfiles/desktop/.emacs.d/lisp/core/keybindings.el b/dotfiles/desktop/.emacs.d/lisp/core/keybindings.el index da0df80..1992bdd 100644 --- a/dotfiles/desktop/.emacs.d/lisp/core/keybindings.el +++ b/dotfiles/desktop/.emacs.d/lisp/core/keybindings.el @@ -59,12 +59,6 @@ (with-eval-after-load 'vterm (define-key vterm-mode-map (kbd "C-c C-t") #'vterm-copy-mode)) -;; -------- mu4e -------- -(autoload 'mu4e "mu4e" nil t) -(autoload 'mu4e-compose-new "mu4e" nil t) -(global-set-key (kbd "C-x m") #'mu4e-compose-new) -(define-key fscotto/open (kbd "m") #'mu4e) - ;; -------- elfeed -------- (autoload 'elfeed "elfeed" nil t) (define-key fscotto/open (kbd "f") #'fscotto/elfeed-load-db-and-open) diff --git a/dotfiles/desktop/.emacs.d/lisp/misc/which-key.el b/dotfiles/desktop/.emacs.d/lisp/misc/which-key.el index 44854c5..ec25651 100644 --- a/dotfiles/desktop/.emacs.d/lisp/misc/which-key.el +++ b/dotfiles/desktop/.emacs.d/lisp/misc/which-key.el @@ -24,7 +24,7 @@ "C-c p" "Project" "C-c d" "Debug" "C-c g" "Git" - "C-c e" "Email / Elfeed") + "C-c e" "Elfeed") ;; -------------------------------------------------------------------------- ;; Open (C-c o …) @@ -33,7 +33,6 @@ "C-c o d" "Dirvish" "C-c o f" "RSS (Elfeed)" "C-c o l" "LLM chat (gptel)" - "C-c o m" "mu4e (Email Client)" "C-c o T" "Terminal (multi-vterm)" "C-c o z" "Ztree diff") diff --git a/dotfiles/desktop/.emacs.d/scripts/email_sync.sh b/dotfiles/desktop/.emacs.d/scripts/email_sync.sh deleted file mode 100755 index 1b4c212..0000000 --- a/dotfiles/desktop/.emacs.d/scripts/email_sync.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env sh - -mbsync -a & pid1=$! -wait $pid1 - -mu index -