From c9ad30c1136d4296005aac838939cd6370c9a027 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Wed, 18 Mar 2026 15:00:56 +0100 Subject: [PATCH] Template private desktop mail configs Render personal desktop configs from Ansible templates so public dotfiles no longer expose real identities or mail addresses. Update the bootstrap workflow to consume the rendered mail config and extend the encrypted vault schema for the new private values. --- ansible/inventory/group_vars/desktop.yml | 12 --- .../roles/profile_desktop_i3/tasks/main.yml | 23 +++++ ansible/templates/desktop/.gitconfig.j2 | 83 +++++++++++++++++++ ansible/templates/desktop/.mbsyncrc.j2 | 47 +++++++++++ ansible/templates/desktop/.msmtprc.j2 | 51 ++++++++++++ ansible/templates/desktop/email.el.j2 | 51 ++++++++++++ scripts/bootstrap_mail.sh | 2 +- secrets/vault.yml | 26 ++++-- secrets/vault.yml.example | 5 ++ 9 files changed, 280 insertions(+), 20 deletions(-) create mode 100644 ansible/templates/desktop/.gitconfig.j2 create mode 100644 ansible/templates/desktop/.mbsyncrc.j2 create mode 100644 ansible/templates/desktop/.msmtprc.j2 create mode 100644 ansible/templates/desktop/email.el.j2 diff --git a/ansible/inventory/group_vars/desktop.yml b/ansible/inventory/group_vars/desktop.yml index 8e055e1..d2a6413 100644 --- a/ansible/inventory/group_vars/desktop.yml +++ b/ansible/inventory/group_vars/desktop.yml @@ -114,10 +114,6 @@ desktop_dotfiles: src: .xinitrc dest: .xinitrc mode: "0644" - - name: .gitconfig - src: .gitconfig - dest: .gitconfig - mode: "0644" - name: .gitignore_global src: .gitignore_global dest: .gitignore_global @@ -126,14 +122,6 @@ desktop_dotfiles: src: .themes.gitignore dest: .themes.gitignore mode: "0644" - - name: .mbsyncrc - src: .mbsyncrc - dest: .mbsyncrc - mode: "0600" - - name: .msmtprc - src: .msmtprc - dest: .msmtprc - mode: "0600" - name: Emacs config src: .emacs.d/ dest: .emacs.d/ diff --git a/ansible/roles/profile_desktop_i3/tasks/main.yml b/ansible/roles/profile_desktop_i3/tasks/main.yml index b50ed9e..91c321c 100644 --- a/ansible/roles/profile_desktop_i3/tasks/main.yml +++ b/ansible/roles/profile_desktop_i3/tasks/main.yml @@ -47,6 +47,29 @@ loop_control: label: "{{ item.dest }}" +- name: Render desktop templates with private values + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ user_home }}/{{ item.dest }}" + 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 }}" + - name: Refresh user font cache ansible.builtin.command: fc-cache -f become_user: "{{ username }}" diff --git a/ansible/templates/desktop/.gitconfig.j2 b/ansible/templates/desktop/.gitconfig.j2 new file mode 100644 index 0000000..8a8bb14 --- /dev/null +++ b/ansible/templates/desktop/.gitconfig.j2 @@ -0,0 +1,83 @@ +[init] + defaultBranch = main + +[core] + excludesfile = ~/.gitignore_global + pager = delta + +[user] + name = {{ vault_personal_full_name }} + email = {{ vault_git_email }} + signingkey = {{ vault_git_signing_key }} + +[fetch] + prune = true + +[remote "origin"] + prune = true + +[pull] + rebase = true + +[commit] + gpgsign = false + +[merge] + conflictstyle = diff3 + tool = meld + +[mergetool] + prompt = false + +[diff] + tool = meld + +[color] + ui = always + +[color "status"] + branch = magenta + untracked = cyan + unmerged = yellow bold + +[color "diff"] + frag = magenta bold + old = red bold + new = green bold + whitespace = red reverse + +[color "diff-highlight"] + oldNormal = red bold + oldHighlight = red bold 52 + newNormal = green bold + newHighlight = green bold 52 + +[help] + autocorrect = 30 + +[interactive] + diffFilter = delta --color-only + +[alias] + co = checkout + br = branch + ci = commit + st = status + ld = log -p + lg = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)%n' --all + glog = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' + onelinegraph = log --oneline --graph --decorate + undo = reset --soft HEAD~1 + stash-all = stash save --include-untracked + expireunreachablenow = reflog expire --expire-unreachable=now --all + gcunreachablenow = gc --prune=now + +[include] + path = ~/.themes.gitignore + +[delta] + features = catppuccin-mocha navigate + true-color = always + colorMoved = default + tabs = 4 + side-by-side = true diff --git a/ansible/templates/desktop/.mbsyncrc.j2 b/ansible/templates/desktop/.mbsyncrc.j2 new file mode 100644 index 0000000..ce7ce8c --- /dev/null +++ b/ansible/templates/desktop/.mbsyncrc.j2 @@ -0,0 +1,47 @@ +##################### iCloud Account ################################## +IMAPStore iCloud-remote + Host imap.mail.me.com + Port 993 + User {{ vault_icloud_email }} + PassCmd "secret-tool lookup icloud-mail icloud" + AuthMechs * + SSLType IMAPS + SSLVersions TLSv1.2 TLSv1.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 * + SSLType STARTTLS + PipelineDepth 1 + CertificateFile ~/.config/protonmail/bridge-v3/cert.pem + +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 new file mode 100644 index 0000000..9744697 --- /dev/null +++ b/ansible/templates/desktop/.msmtprc.j2 @@ -0,0 +1,51 @@ +# 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 ~/.config/protonmail/bridge-v3/cert.pem + +# 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 new file mode 100644 index 0000000..39125fb --- /dev/null +++ b/ansible/templates/desktop/email.el.j2 @@ -0,0 +1,51 @@ +;;; 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" + 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/scripts/bootstrap_mail.sh b/scripts/bootstrap_mail.sh index 286f71d..7f21335 100755 --- a/scripts/bootstrap_mail.sh +++ b/scripts/bootstrap_mail.sh @@ -4,7 +4,7 @@ set -eu SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd) REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd) -MBSYNCRC="$REPO_ROOT/dotfiles/desktop/.mbsyncrc" +MBSYNCRC="$HOME/.mbsyncrc" VAULT_FILE="$REPO_ROOT/secrets/vault.yml" ACCOUNTS_FILE=$(mktemp) diff --git a/secrets/vault.yml b/secrets/vault.yml index e8a8305..812f3aa 100644 --- a/secrets/vault.yml +++ b/secrets/vault.yml @@ -1,8 +1,20 @@ $ANSIBLE_VAULT;1.1;AES256 -35326663666435356232666461316532653434653734613832646461666566373762613863653630 -6661663665613230343037313762643662663339383339320a366562326231663637643639633431 -62663231386339343033633662363531623931386239343532636530353735623233396238613666 -3330653433356539320a353930626335663331333433386139393538343232636161396464306632 -66336530366531656261316634663265363731666638323863313762373766303839363463633835 -66653733373961636165393462376561666531343230626338333333373663613133633937336539 -353632303535393564636232626135313630 +38303735393730383864306232356663336631386465323862303331633835356361323433386562 +3639303563376361396265663331626133313934353838300a336134386661396138316533303830 +38663636653964366132636438306334633265316139663962623437626338373961386564613934 +3139343336646365330a643165366531366466646235363431386639643239313838353736373562 +37616466383239346666313865646666373264303764373234366333316433646637343632346661 +35326431333239376432336261656264303365663261303965396630366438666566663039376635 +36653061393736303939663032663063643064393566353436666232356338343765613530343137 +66386231373765623366323335646231323339356666326366303464313234626364386539646131 +64396461346137323065383665333462623363643561323431363737613332346331623063613732 +30363464633234316232623030666666623663373738613839306333663432363461363261633437 +64346331316336653533656530333061303934636634333763643434663834343166343135663930 +31633336663363316530336133663734316533303132613363656338656537363938313932623464 +64653335646335366135653534643839623332306661623266326663326236366563373738306665 +37306338613539623135393334646236303562356664343631366461366233323966633466323733 +38373632393837346430663335633563323139313737303039623161633766343531373162643134 +35323065633736303634393638613131386565373139326636633830363131646232336165636465 +36633963363062633965393633333164663063313462386264353162633439376234643534613339 +36383066316161623264343636336665313533653761356334653137353661646162366434646435 +656435383861346366653734616231623230 diff --git a/secrets/vault.yml.example b/secrets/vault.yml.example index e071e94..acf7acb 100644 --- a/secrets/vault.yml.example +++ b/secrets/vault.yml.example @@ -1,2 +1,7 @@ --- +vault_personal_full_name: "REPLACE_ME" +vault_git_email: "REPLACE_ME" +vault_git_signing_key: "REPLACE_ME" +vault_icloud_email: "REPLACE_ME" +vault_protonmail_email: "REPLACE_ME" vault_icloud_mail_password: "REPLACE_ME"