new version after nix
This commit is contained in:
@@ -0,0 +1,88 @@
|
|||||||
|
# Fedora Sway workstation
|
||||||
|
|
||||||
|
An Ansible playbook for rebuilding the two NixOS workstation hosts as a native
|
||||||
|
Fedora Sway desktop. The NixOS server host (`sta-len-nix`) and its services,
|
||||||
|
WireGuard, firewall, and Netdata configuration are intentionally excluded.
|
||||||
|
|
||||||
|
## Target
|
||||||
|
|
||||||
|
- Native Fedora 44 on x86_64
|
||||||
|
- Sway with SDDM, Waybar, PipeWire, printing, SSH, and NetworkManager
|
||||||
|
- Faroese keyboard layout, Danish regional formats, and Atlantic/Faroe time
|
||||||
|
- Foot as the terminal, opening the persistent `tmux` session
|
||||||
|
- Zen as the default browser, installed from Zen's official release tarball
|
||||||
|
- Development tools, formatters, and Fedora-packaged language servers from NixOS
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
Install Ansible as the normal desktop user:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dnf install -y ansible
|
||||||
|
git clone https://codeberg.org/bartal-lsn/fedora-provisioning.git
|
||||||
|
cd fedora-provisioning
|
||||||
|
ansible-playbook setup.yml --ask-become-pass
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not start the playbook with `sudo`. It uses privilege escalation only for
|
||||||
|
system tasks and installs Zen and user configuration into the invoking user's
|
||||||
|
home directory. Log out or reboot after the first run to enter Sway through
|
||||||
|
SDDM and pick up the new group memberships and environment.
|
||||||
|
|
||||||
|
## Configuration ownership
|
||||||
|
|
||||||
|
The Home Manager configuration lives in the public
|
||||||
|
`https://codeberg.org/bartal-lsn/dotfiles` repository as GNU Stow packages.
|
||||||
|
During provisioning, Ansible clones or updates that repository at
|
||||||
|
`~/dotfiles`, then runs `stow -R *` from that directory. Stow therefore
|
||||||
|
restows every package into the user's home directory.
|
||||||
|
|
||||||
|
Commit dotfile changes to the Codeberg repository, then rerun the playbook to
|
||||||
|
pull `~/dotfiles` and refresh its links. Editor-managed binaries such as `zls`,
|
||||||
|
`omnisharp`, `jdtls`, and `lua-language-server` remain Neovim concerns because
|
||||||
|
Fedora does not package them consistently. Ansible installs Fedora's `clangd`
|
||||||
|
and `gopls`, Pyright, TypeScript language server, Black, isort, Prettier, and
|
||||||
|
StyLua. Rust and `rust-analyzer` are installed through the official rustup
|
||||||
|
installer.
|
||||||
|
|
||||||
|
## Desktop keys
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|---|---|
|
||||||
|
| `Super+t` | Foot attached to tmux session `main` |
|
||||||
|
| `Super+b` | Zen Browser |
|
||||||
|
| `Super+d` | Rofi application launcher |
|
||||||
|
| `Super+q` | Close window |
|
||||||
|
| `Super+h/j/k/l` | Move focus |
|
||||||
|
| `Super+Shift+h/j/k/l` | Move window |
|
||||||
|
| `Super+1..0` | Switch workspace |
|
||||||
|
| `Super+Shift+1..0` | Move window to workspace |
|
||||||
|
| `Super+f` | Toggle fullscreen |
|
||||||
|
| `Super+Shift+Space` | Toggle floating |
|
||||||
|
| `Super+-` | Show scratchpad |
|
||||||
|
| `Super+Shift+-` | Move window to scratchpad |
|
||||||
|
|
||||||
|
## Optional behavior
|
||||||
|
|
||||||
|
The main switches live near the top of `vars.yml`:
|
||||||
|
|
||||||
|
- `upgrade_system`: upgrade packages before provisioning
|
||||||
|
- `install_virtualization`: install Fedora's libvirt virtualization group
|
||||||
|
- `install_sqlcmd`: retain the Fedora repository's existing SQL Server CLI
|
||||||
|
- `install_typora`: install the unverified Flathub Typora wrapper
|
||||||
|
|
||||||
|
The playbook installs OpenJDK 25 because Fedora 44 does not publish the
|
||||||
|
OpenJDK 21 RPM used by the NixOS setup.
|
||||||
|
|
||||||
|
Fedora does not have a direct equivalent for NixOS's
|
||||||
|
`virtualisation.vmware.host.enable`; this playbook uses Fedora's supported
|
||||||
|
libvirt stack instead. Typora is optional because its Flathub wrapper is not
|
||||||
|
verified by Typora. Zen never uses Flatpak: Ansible downloads the official
|
||||||
|
release archive directly, places it under `~/.tarball-installations/zen`, and
|
||||||
|
creates the `~/.local/bin/zen` launcher.
|
||||||
|
|
||||||
|
## Re-running
|
||||||
|
|
||||||
|
The playbook is designed to be repeatable. Zen, Bun, Rust, Starship, npm tools,
|
||||||
|
services, and configuration files are checked before changes are made. Zen
|
||||||
|
handles browser updates itself after the initial binary installation.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = inventory.ini
|
||||||
|
inject_facts_as_vars = False
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[workstation]
|
||||||
|
localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
- name: Configure Fedora Sway workstation
|
||||||
|
hosts: workstation
|
||||||
|
become: true
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars.yml
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: Verify that the target is Fedora
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- ansible_facts["distribution"] == "Fedora"
|
||||||
|
- ansible_facts["distribution_major_version"] == "44"
|
||||||
|
- ansible_facts["architecture"] == "x86_64"
|
||||||
|
fail_msg: "This playbook supports native Fedora 44 x86_64 workstations."
|
||||||
|
|
||||||
|
- name: Verify that the workstation user is not root
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- user_name != "root"
|
||||||
|
- user_home != "/root"
|
||||||
|
fail_msg: "Run ansible-playbook as the workstation user, using --ask-become-pass for sudo."
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- ansible.builtin.import_tasks: tasks/dnf_packages.yml
|
||||||
|
- ansible.builtin.import_tasks: tasks/system.yml
|
||||||
|
- ansible.builtin.import_tasks: tasks/services.yml
|
||||||
|
- ansible.builtin.import_tasks: tasks/tooling.yml
|
||||||
|
- ansible.builtin.import_tasks: tasks/sqlcmd.yml
|
||||||
|
when: install_sqlcmd
|
||||||
|
- ansible.builtin.import_tasks: tasks/zen.yml
|
||||||
|
- ansible.builtin.import_tasks: tasks/dotfiles.yml
|
||||||
|
- ansible.builtin.import_tasks: tasks/user_config.yml
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
- name: Enable RPM Fusion free repository
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: "https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-{{ ansible_facts['distribution_major_version'] }}.noarch.rpm"
|
||||||
|
state: present
|
||||||
|
disable_gpg_check: true
|
||||||
|
|
||||||
|
- name: Upgrade installed Fedora packages
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: "*"
|
||||||
|
state: latest
|
||||||
|
update_cache: true
|
||||||
|
when: upgrade_system
|
||||||
|
|
||||||
|
- name: Install Fedora workstation packages
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: "{{ fedora_packages }}"
|
||||||
|
state: present
|
||||||
|
allowerasing: true
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Install virtualization package group
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: "{{ virtualization_packages }}"
|
||||||
|
state: present
|
||||||
|
when: install_virtualization
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
- name: Ensure Stow target directories exist
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item.path }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ user_name }}"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- { path: "{{ user_home }}/.config", mode: "0755" }
|
||||||
|
- { path: "{{ user_home }}/.ssh", mode: "0700" }
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Clone or update the public dotfiles repository
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: "{{ dotfiles_repo }}"
|
||||||
|
dest: "{{ dotfiles_dir }}"
|
||||||
|
version: main
|
||||||
|
update: true
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Install all dotfiles with GNU Stow
|
||||||
|
ansible.builtin.shell: stow -R *
|
||||||
|
args:
|
||||||
|
chdir: "{{ dotfiles_dir }}"
|
||||||
|
executable: /bin/bash
|
||||||
|
become: false
|
||||||
|
changed_when: false
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
- name: Enable workstation system services
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: "{{ item }}"
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
loop:
|
||||||
|
- NetworkManager.service
|
||||||
|
- cups.service
|
||||||
|
- sshd.service
|
||||||
|
|
||||||
|
- name: Select SDDM as the display manager
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: /usr/lib/systemd/system/sddm.service
|
||||||
|
dest: /etc/systemd/system/display-manager.service
|
||||||
|
state: link
|
||||||
|
force: true
|
||||||
|
|
||||||
|
- name: Use the graphical boot target
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: /usr/lib/systemd/system/graphical.target
|
||||||
|
dest: /etc/systemd/system/default.target
|
||||||
|
state: link
|
||||||
|
force: true
|
||||||
|
|
||||||
|
- name: Reload systemd after selecting the display manager
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: Enable libvirt
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: libvirtd.service
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
when: install_virtualization
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
- name: Check if sqlcmd is already installed
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /usr/local/bin/sqlcmd
|
||||||
|
register: sqlcmd_bin
|
||||||
|
|
||||||
|
- name: Download sqlcmd archive
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "{{ sqlcmd_url }}"
|
||||||
|
dest: "/tmp/{{ sqlcmd_archive }}"
|
||||||
|
when: not sqlcmd_bin.stat.exists
|
||||||
|
|
||||||
|
- name: Create sqlcmd extraction directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /tmp/sqlcmd_extract
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
when: not sqlcmd_bin.stat.exists
|
||||||
|
|
||||||
|
- name: Extract sqlcmd
|
||||||
|
ansible.builtin.unarchive:
|
||||||
|
src: "/tmp/{{ sqlcmd_archive }}"
|
||||||
|
dest: /tmp/sqlcmd_extract
|
||||||
|
remote_src: true
|
||||||
|
creates: /tmp/sqlcmd_extract/sqlcmd
|
||||||
|
when: not sqlcmd_bin.stat.exists
|
||||||
|
|
||||||
|
- name: Move sqlcmd binary to /usr/local/bin
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: /tmp/sqlcmd_extract/sqlcmd
|
||||||
|
dest: /usr/local/bin/sqlcmd
|
||||||
|
mode: "0755"
|
||||||
|
remote_src: true
|
||||||
|
when: not sqlcmd_bin.stat.exists
|
||||||
|
|
||||||
|
- name: Clean up sqlcmd temp files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: absent
|
||||||
|
loop:
|
||||||
|
- "/tmp/{{ sqlcmd_archive }}"
|
||||||
|
- /tmp/sqlcmd_extract
|
||||||
|
when: not sqlcmd_bin.stat.exists
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
---
|
||||||
|
- name: Read the configured timezone
|
||||||
|
ansible.builtin.command: timedatectl show --property=Timezone --value
|
||||||
|
register: configured_timezone
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Set the system timezone
|
||||||
|
ansible.builtin.command: "timedatectl set-timezone {{ system_timezone }}"
|
||||||
|
when: configured_timezone.stdout != system_timezone
|
||||||
|
|
||||||
|
- name: Configure system locale
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/locale.conf
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
LANG={{ system_locale }}
|
||||||
|
LC_ADDRESS={{ regional_locale }}
|
||||||
|
LC_IDENTIFICATION={{ regional_locale }}
|
||||||
|
LC_MEASUREMENT={{ regional_locale }}
|
||||||
|
LC_MONETARY={{ regional_locale }}
|
||||||
|
LC_NAME={{ regional_locale }}
|
||||||
|
LC_NUMERIC={{ regional_locale }}
|
||||||
|
LC_PAPER={{ regional_locale }}
|
||||||
|
LC_TELEPHONE={{ regional_locale }}
|
||||||
|
LC_TIME={{ regional_locale }}
|
||||||
|
|
||||||
|
- name: Configure console keyboard
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/vconsole.conf
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
KEYMAP=dk
|
||||||
|
|
||||||
|
- name: Add workstation user to administrative and device groups
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ user_name }}"
|
||||||
|
groups: "{{ ['wheel', 'video', 'input'] + (['libvirt'] if install_virtualization else []) }}"
|
||||||
|
append: true
|
||||||
|
shell: /usr/bin/zsh
|
||||||
|
|
||||||
|
- name: Check transparent hugepage kernel argument
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
grubby --info=ALL | awk '
|
||||||
|
/^args=/ {
|
||||||
|
seen = 1
|
||||||
|
if (index($0, "transparent_hugepage=never") == 0) missing = 1
|
||||||
|
}
|
||||||
|
END { exit !(seen && !missing) }
|
||||||
|
'
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: transparent_hugepage_argument
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Disable transparent hugepages in all boot entries
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- grubby
|
||||||
|
- --update-kernel=ALL
|
||||||
|
- --args=transparent_hugepage=never
|
||||||
|
when: transparent_hugepage_argument.rc != 0
|
||||||
|
|
||||||
|
- name: Configure workstation environment
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/profile.d/fedora-workstation.sh
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||||
|
export GOPATH="${GOPATH:-$HOME/go}"
|
||||||
|
export PATH="$HOME/.scripts:$HOME/.local/bin:$HOME/.cargo/bin:$HOME/.bun/bin:$HOME/bin/zig:$HOME/bin/zls:$GOPATH/bin:$PATH"
|
||||||
|
export TERMINAL=foot
|
||||||
|
export BROWSER=zen
|
||||||
|
export GTK_THEME=Adwaita:dark
|
||||||
|
export MOZ_ENABLE_WAYLAND=1
|
||||||
|
export ELECTRON_OZONE_PLATFORM_HINT=wayland
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
---
|
||||||
|
- name: List globally installed npm packages
|
||||||
|
ansible.builtin.command: npm list --global --depth=0 --json
|
||||||
|
register: npm_global_list
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Install global language servers and formatters
|
||||||
|
ansible.builtin.command: "npm install --global {{ item }}"
|
||||||
|
loop: "{{ npm_global_packages }}"
|
||||||
|
when: item not in ((npm_global_list.stdout | default('{}', true) | from_json).dependencies | default({}))
|
||||||
|
|
||||||
|
- name: Check for rustup
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ user_home }}/.cargo/bin/rustup"
|
||||||
|
become: false
|
||||||
|
register: rustup_binary
|
||||||
|
|
||||||
|
- name: Download the official rustup installer
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: https://sh.rustup.rs
|
||||||
|
dest: /tmp/rustup-init.sh
|
||||||
|
mode: "0755"
|
||||||
|
when: not rustup_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Install Rust stable with the official rustup installer
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- /tmp/rustup-init.sh
|
||||||
|
- -y
|
||||||
|
- --default-toolchain
|
||||||
|
- stable
|
||||||
|
- --profile
|
||||||
|
- default
|
||||||
|
environment:
|
||||||
|
HOME: "{{ user_home }}"
|
||||||
|
become: false
|
||||||
|
when: not rustup_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Remove the rustup installer
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /tmp/rustup-init.sh
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Check the active Rust toolchain
|
||||||
|
ansible.builtin.command: "{{ user_home }}/.cargo/bin/rustup show active-toolchain"
|
||||||
|
become: false
|
||||||
|
register: active_rust_toolchain
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Select the Rust stable toolchain
|
||||||
|
ansible.builtin.command: "{{ user_home }}/.cargo/bin/rustup default stable"
|
||||||
|
become: false
|
||||||
|
when: active_rust_toolchain.rc != 0 or not active_rust_toolchain.stdout.startswith('stable-')
|
||||||
|
|
||||||
|
- name: List installed rustup components
|
||||||
|
ansible.builtin.command: "{{ user_home }}/.cargo/bin/rustup component list --installed"
|
||||||
|
become: false
|
||||||
|
register: installed_rustup_components
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Install Rust development components
|
||||||
|
ansible.builtin.command: "{{ user_home }}/.cargo/bin/rustup component add {{ item }}"
|
||||||
|
loop: "{{ rustup_components }}"
|
||||||
|
become: false
|
||||||
|
when: installed_rustup_components.stdout_lines | select('match', '^' ~ item ~ '(-|$)') | list | length == 0
|
||||||
|
|
||||||
|
- name: Check for StyLua
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ user_home }}/.cargo/bin/stylua"
|
||||||
|
become: false
|
||||||
|
register: stylua_binary
|
||||||
|
|
||||||
|
- name: Install StyLua
|
||||||
|
ansible.builtin.command: "{{ user_home }}/.cargo/bin/cargo install stylua --locked"
|
||||||
|
become: false
|
||||||
|
when: not stylua_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Check for Starship
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ user_home }}/.local/bin/starship"
|
||||||
|
become: false
|
||||||
|
register: starship_binary
|
||||||
|
|
||||||
|
- name: Download the Starship installer
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: https://starship.rs/install.sh
|
||||||
|
dest: /tmp/starship-install.sh
|
||||||
|
mode: "0755"
|
||||||
|
when: not starship_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Install Starship for the workstation user
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- /tmp/starship-install.sh
|
||||||
|
- --yes
|
||||||
|
- --bin-dir
|
||||||
|
- "{{ user_home }}/.local/bin"
|
||||||
|
become: false
|
||||||
|
when: not starship_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Check for Bun
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ user_home }}/.bun/bin/bun"
|
||||||
|
become: false
|
||||||
|
register: bun_binary
|
||||||
|
|
||||||
|
- name: Download the Bun installer
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: https://bun.sh/install
|
||||||
|
dest: /tmp/bun-install.sh
|
||||||
|
mode: "0755"
|
||||||
|
when: not bun_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Install Bun for the workstation user
|
||||||
|
ansible.builtin.command: /tmp/bun-install.sh
|
||||||
|
become: false
|
||||||
|
when: not bun_binary.stat.exists
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
- name: Create Ansible-managed user directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item.path }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ user_name }}"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- { path: "{{ user_home }}/.ssh", mode: "0700" }
|
||||||
|
- { path: "{{ user_home }}/Pictures", mode: "0755" }
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Check for the Git signing public key
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ git_signing_key }}"
|
||||||
|
become: false
|
||||||
|
register: git_signing_public_key
|
||||||
|
|
||||||
|
- name: Read the Git signing public key
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ git_signing_key }}"
|
||||||
|
become: false
|
||||||
|
register: git_signing_public_key_contents
|
||||||
|
when: git_signing_public_key.stat.exists
|
||||||
|
|
||||||
|
- name: Configure allowed SSH signers
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ user_home }}/.ssh/allowed_signers"
|
||||||
|
owner: "{{ user_name }}"
|
||||||
|
mode: "0644"
|
||||||
|
content: "{{ git_email }} {{ git_signing_public_key_contents.content | b64decode | trim }}\n"
|
||||||
|
become: false
|
||||||
|
when: git_signing_public_key.stat.exists
|
||||||
|
|
||||||
|
- name: Install Typora from Flathub
|
||||||
|
when: install_typora
|
||||||
|
block:
|
||||||
|
- name: Ensure Flathub is configured
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- flatpak
|
||||||
|
- remote-add
|
||||||
|
- --if-not-exists
|
||||||
|
- flathub
|
||||||
|
- https://flathub.org/repo/flathub.flatpakrepo
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Check for Typora
|
||||||
|
ansible.builtin.command: flatpak info io.typora.Typora
|
||||||
|
register: typora_flatpak
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Install Typora
|
||||||
|
ansible.builtin.command: flatpak install --noninteractive flathub io.typora.Typora
|
||||||
|
when: typora_flatpak.rc != 0
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
- name: Check for Zen Browser
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ zen_install_dir }}/zen"
|
||||||
|
become: false
|
||||||
|
register: zen_binary
|
||||||
|
|
||||||
|
- name: Create Zen installation directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ user_name }}"
|
||||||
|
mode: "0755"
|
||||||
|
become: false
|
||||||
|
loop:
|
||||||
|
- "{{ user_home }}/.tarball-installations"
|
||||||
|
- "{{ user_home }}/.config"
|
||||||
|
- "{{ user_home }}/.local/bin"
|
||||||
|
- "{{ user_home }}/.local/share/applications"
|
||||||
|
- "{{ user_home }}/.local/share/icons/hicolor/128x128/apps"
|
||||||
|
|
||||||
|
- name: Download the current Zen release binary
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "{{ zen_archive_url }}"
|
||||||
|
dest: "{{ zen_archive }}"
|
||||||
|
mode: "0644"
|
||||||
|
become: false
|
||||||
|
when: not zen_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Extract Zen Browser
|
||||||
|
ansible.builtin.unarchive:
|
||||||
|
src: "{{ zen_archive }}"
|
||||||
|
dest: "{{ user_home }}/.tarball-installations"
|
||||||
|
remote_src: true
|
||||||
|
creates: "{{ zen_install_dir }}/zen"
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Link Zen into the user's PATH
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: "{{ zen_install_dir }}/zen"
|
||||||
|
dest: "{{ user_home }}/.local/bin/zen"
|
||||||
|
state: link
|
||||||
|
force: true
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Install Zen application icon
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ zen_install_dir }}/browser/chrome/icons/default/default128.png"
|
||||||
|
dest: "{{ user_home }}/.local/share/icons/hicolor/128x128/apps/zen.png"
|
||||||
|
remote_src: true
|
||||||
|
owner: "{{ user_name }}"
|
||||||
|
mode: "0644"
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Install Zen desktop entry
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ user_home }}/.local/share/applications/{{ zen_desktop_file }}"
|
||||||
|
owner: "{{ user_name }}"
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=Zen Browser
|
||||||
|
Comment=Browse the web
|
||||||
|
Exec=zen %u
|
||||||
|
Icon=zen
|
||||||
|
Terminal=false
|
||||||
|
StartupNotify=true
|
||||||
|
StartupWMClass=zen
|
||||||
|
Categories=Network;WebBrowser;
|
||||||
|
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;application/x-xpinstall;application/pdf;application/json;
|
||||||
|
Actions=new-window;new-private-window;profile-manager;
|
||||||
|
|
||||||
|
[Desktop Action new-window]
|
||||||
|
Name=New Window
|
||||||
|
Exec=zen --new-window %u
|
||||||
|
|
||||||
|
[Desktop Action new-private-window]
|
||||||
|
Name=New Private Window
|
||||||
|
Exec=zen --private-window %u
|
||||||
|
|
||||||
|
[Desktop Action profile-manager]
|
||||||
|
Name=Profile Manager
|
||||||
|
Exec=zen --ProfileManager
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Remove downloaded Zen archive
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ zen_archive }}"
|
||||||
|
state: absent
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Query default MIME handlers
|
||||||
|
ansible.builtin.command: "xdg-mime query default {{ item }}"
|
||||||
|
become: false
|
||||||
|
loop:
|
||||||
|
- text/html
|
||||||
|
- application/xhtml+xml
|
||||||
|
- x-scheme-handler/http
|
||||||
|
- x-scheme-handler/https
|
||||||
|
register: current_browser_handlers
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Set Zen as the default browser
|
||||||
|
ansible.builtin.command: "xdg-mime default {{ zen_desktop_file }} {{ item.item }}"
|
||||||
|
become: false
|
||||||
|
loop: "{{ current_browser_handlers.results }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.item }}"
|
||||||
|
when: item.stdout != zen_desktop_file
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# Sway workstation configuration translated from NixOS behavior.
|
||||||
|
set $mod Mod4
|
||||||
|
set $term foot -e tmux new-session -A -s main
|
||||||
|
set $browser zen
|
||||||
|
set $menu rofi -show drun
|
||||||
|
|
||||||
|
font pango:DejaVu Sans Mono 10
|
||||||
|
|
||||||
|
output * scale 1
|
||||||
|
output * bg ~/.config/sway/tux.png fill
|
||||||
|
|
||||||
|
input type:keyboard {
|
||||||
|
xkb_layout {{ keyboard_layout }}
|
||||||
|
xkb_model pc105
|
||||||
|
}
|
||||||
|
|
||||||
|
input type:touchpad {
|
||||||
|
natural_scroll disabled
|
||||||
|
tap enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
gaps inner 5
|
||||||
|
gaps outer 10
|
||||||
|
smart_gaps on
|
||||||
|
default_border pixel 2
|
||||||
|
default_floating_border pixel 2
|
||||||
|
|
||||||
|
client.focused #33ccff #33ccff #1a1b26 #33ccff #33ccff
|
||||||
|
client.focused_inactive #595959 #595959 #c0caf5 #595959 #595959
|
||||||
|
client.unfocused #595959 #595959 #c0caf5 #595959 #595959
|
||||||
|
|
||||||
|
floating_modifier $mod normal
|
||||||
|
|
||||||
|
# Applications and session
|
||||||
|
bindsym $mod+t exec $term
|
||||||
|
bindsym $mod+b exec $browser
|
||||||
|
bindsym $mod+d exec $menu
|
||||||
|
bindsym $mod+q kill
|
||||||
|
bindsym $mod+Shift+c reload
|
||||||
|
bindsym $mod+Shift+e exec swaynag -t warning -m 'Exit Sway?' -B 'Exit' 'swaymsg exit'
|
||||||
|
|
||||||
|
# Focus movement
|
||||||
|
bindsym $mod+h focus left
|
||||||
|
bindsym $mod+j focus down
|
||||||
|
bindsym $mod+k focus up
|
||||||
|
bindsym $mod+l focus right
|
||||||
|
bindsym $mod+Left focus left
|
||||||
|
bindsym $mod+Down focus down
|
||||||
|
bindsym $mod+Up focus up
|
||||||
|
bindsym $mod+Right focus right
|
||||||
|
|
||||||
|
# Move windows
|
||||||
|
bindsym $mod+Shift+h move left
|
||||||
|
bindsym $mod+Shift+j move down
|
||||||
|
bindsym $mod+Shift+k move up
|
||||||
|
bindsym $mod+Shift+l move right
|
||||||
|
bindsym $mod+Shift+Left move left
|
||||||
|
bindsym $mod+Shift+Down move down
|
||||||
|
bindsym $mod+Shift+Up move up
|
||||||
|
bindsym $mod+Shift+Right move right
|
||||||
|
|
||||||
|
# Workspaces
|
||||||
|
set $ws1 1
|
||||||
|
set $ws2 2
|
||||||
|
set $ws3 3
|
||||||
|
set $ws4 4
|
||||||
|
set $ws5 5
|
||||||
|
set $ws6 6
|
||||||
|
set $ws7 7
|
||||||
|
set $ws8 8
|
||||||
|
set $ws9 9
|
||||||
|
set $ws10 10
|
||||||
|
|
||||||
|
bindsym $mod+1 workspace number $ws1
|
||||||
|
bindsym $mod+2 workspace number $ws2
|
||||||
|
bindsym $mod+3 workspace number $ws3
|
||||||
|
bindsym $mod+4 workspace number $ws4
|
||||||
|
bindsym $mod+5 workspace number $ws5
|
||||||
|
bindsym $mod+6 workspace number $ws6
|
||||||
|
bindsym $mod+7 workspace number $ws7
|
||||||
|
bindsym $mod+8 workspace number $ws8
|
||||||
|
bindsym $mod+9 workspace number $ws9
|
||||||
|
bindsym $mod+0 workspace number $ws10
|
||||||
|
|
||||||
|
bindsym $mod+Shift+1 move container to workspace number $ws1
|
||||||
|
bindsym $mod+Shift+2 move container to workspace number $ws2
|
||||||
|
bindsym $mod+Shift+3 move container to workspace number $ws3
|
||||||
|
bindsym $mod+Shift+4 move container to workspace number $ws4
|
||||||
|
bindsym $mod+Shift+5 move container to workspace number $ws5
|
||||||
|
bindsym $mod+Shift+6 move container to workspace number $ws6
|
||||||
|
bindsym $mod+Shift+7 move container to workspace number $ws7
|
||||||
|
bindsym $mod+Shift+8 move container to workspace number $ws8
|
||||||
|
bindsym $mod+Shift+9 move container to workspace number $ws9
|
||||||
|
bindsym $mod+Shift+0 move container to workspace number $ws10
|
||||||
|
|
||||||
|
# Layout and scratchpad
|
||||||
|
bindsym $mod+s layout toggle split
|
||||||
|
bindsym $mod+e layout toggle split
|
||||||
|
bindsym $mod+f fullscreen toggle
|
||||||
|
bindsym $mod+Shift+space floating toggle
|
||||||
|
bindsym $mod+minus scratchpad show
|
||||||
|
bindsym $mod+Shift+minus move scratchpad
|
||||||
|
|
||||||
|
# Hardware controls
|
||||||
|
bindsym XF86AudioRaiseVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||||
|
bindsym XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||||
|
bindsym XF86AudioMute exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||||
|
bindsym XF86AudioMicMute exec wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||||
|
bindsym XF86MonBrightnessUp exec brightnessctl set 5%+
|
||||||
|
bindsym XF86MonBrightnessDown exec brightnessctl set 5%-
|
||||||
|
bindsym Print exec grim -g "$(slurp)" "$HOME/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png"
|
||||||
|
|
||||||
|
# Session services
|
||||||
|
exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
|
||||||
|
exec /usr/libexec/lxqt-policykit-agent
|
||||||
|
exec nm-applet --indicator
|
||||||
|
exec mako
|
||||||
|
exec ~/.config/waybar/launch.sh
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
---
|
||||||
|
# The playbook must be started as the desktop user, not through sudo.
|
||||||
|
user_name: "{{ lookup('env', 'USER') }}"
|
||||||
|
user_home: "{{ lookup('env', 'HOME') }}"
|
||||||
|
dotfiles_dir: "{{ user_home }}/dotfiles"
|
||||||
|
dotfiles_repo: https://codeberg.org/bartal-lsn/dotfiles.git
|
||||||
|
|
||||||
|
system_timezone: Atlantic/Faroe
|
||||||
|
system_locale: en_US.UTF-8
|
||||||
|
regional_locale: da_DK.UTF-8
|
||||||
|
keyboard_layout: fo
|
||||||
|
|
||||||
|
upgrade_system: true
|
||||||
|
install_virtualization: true
|
||||||
|
install_sqlcmd: true
|
||||||
|
install_typora: true
|
||||||
|
|
||||||
|
fedora_packages:
|
||||||
|
# Media and documents
|
||||||
|
- ffmpeg
|
||||||
|
- fuse
|
||||||
|
- fuse-libs
|
||||||
|
- ghostscript
|
||||||
|
- libheif-tools
|
||||||
|
- libreoffice
|
||||||
|
- libtiff
|
||||||
|
- libwebp
|
||||||
|
- openjpeg
|
||||||
|
|
||||||
|
# Development toolchains and libraries
|
||||||
|
- binutils
|
||||||
|
- clang
|
||||||
|
- clang-tools-extra
|
||||||
|
- composer
|
||||||
|
- dotnet-sdk-10.0
|
||||||
|
- file
|
||||||
|
- gcc
|
||||||
|
- gcc-c++
|
||||||
|
- glibc-langpack-da
|
||||||
|
- glibc-langpack-en
|
||||||
|
- golang
|
||||||
|
- gopls
|
||||||
|
- go-task
|
||||||
|
- hugo
|
||||||
|
- ibus
|
||||||
|
- java-25-openjdk-devel
|
||||||
|
- make
|
||||||
|
- maven
|
||||||
|
- ncurses-devel
|
||||||
|
- nodejs
|
||||||
|
- npm
|
||||||
|
- openssl-devel
|
||||||
|
- php
|
||||||
|
- python3
|
||||||
|
- black
|
||||||
|
- python3-isort
|
||||||
|
- sqlite
|
||||||
|
- tree-sitter-cli
|
||||||
|
- unixODBC
|
||||||
|
- unixODBC-devel
|
||||||
|
- uv
|
||||||
|
- zig
|
||||||
|
|
||||||
|
# Command-line workstation tools
|
||||||
|
- 7zip
|
||||||
|
- acpi
|
||||||
|
- curl
|
||||||
|
- fd-find
|
||||||
|
- findutils
|
||||||
|
- flatpak
|
||||||
|
- fish
|
||||||
|
- fzf
|
||||||
|
- gawk
|
||||||
|
- git
|
||||||
|
- jq
|
||||||
|
- kbd
|
||||||
|
- less
|
||||||
|
- lua
|
||||||
|
- neovim
|
||||||
|
- ripgrep
|
||||||
|
- stow
|
||||||
|
- tar
|
||||||
|
- tmux
|
||||||
|
- unzip
|
||||||
|
- util-linux
|
||||||
|
- vim-enhanced
|
||||||
|
- wget
|
||||||
|
- xz
|
||||||
|
- zip
|
||||||
|
- zsh
|
||||||
|
- zsh-autosuggestions
|
||||||
|
- zsh-syntax-highlighting
|
||||||
|
|
||||||
|
# Native Sway workstation
|
||||||
|
- brightnessctl
|
||||||
|
- foot
|
||||||
|
- gnome-keyring
|
||||||
|
- gnome-keyring-pam
|
||||||
|
- grim
|
||||||
|
- mako
|
||||||
|
- network-manager-applet
|
||||||
|
- nm-connection-editor
|
||||||
|
- pamixer
|
||||||
|
- pavucontrol
|
||||||
|
- pipewire
|
||||||
|
- pipewire-alsa
|
||||||
|
- pipewire-pulseaudio
|
||||||
|
- playerctl
|
||||||
|
- polkit
|
||||||
|
- lxqt-policykit
|
||||||
|
- rofi
|
||||||
|
- rtkit
|
||||||
|
- sddm
|
||||||
|
- sddm-wayland-sway
|
||||||
|
- slurp
|
||||||
|
- sway
|
||||||
|
- swayidle
|
||||||
|
- swaylock
|
||||||
|
- waybar
|
||||||
|
- wireplumber
|
||||||
|
- wl-clipboard
|
||||||
|
- xdg-desktop-portal
|
||||||
|
- xdg-desktop-portal-gtk
|
||||||
|
- xdg-desktop-portal-wlr
|
||||||
|
- xdg-utils
|
||||||
|
|
||||||
|
# Services and system integration
|
||||||
|
- cups
|
||||||
|
- grubby
|
||||||
|
- openssh-server
|
||||||
|
|
||||||
|
virtualization_packages:
|
||||||
|
- "@virtualization"
|
||||||
|
|
||||||
|
npm_global_packages:
|
||||||
|
- prettier
|
||||||
|
- pyright
|
||||||
|
- typescript
|
||||||
|
- typescript-language-server
|
||||||
|
|
||||||
|
rustup_components:
|
||||||
|
- rust-analyzer
|
||||||
|
- rust-src
|
||||||
|
|
||||||
|
# Direct stable release binary published by the verified Zen Browser project.
|
||||||
|
zen_archive_url: https://github.com/zen-browser/desktop/releases/latest/download/zen.linux-x86_64.tar.xz
|
||||||
|
zen_archive: /tmp/zen.linux-x86_64.tar.xz
|
||||||
|
zen_install_dir: "{{ user_home }}/.tarball-installations/zen"
|
||||||
|
zen_desktop_file: zen.desktop
|
||||||
|
|
||||||
|
# Existing Fedora-only tool retained from this repository.
|
||||||
|
sqlcmd_version: "1.8.1"
|
||||||
|
sqlcmd_archive: sqlcmd-linux-amd64.tar.bz2
|
||||||
|
sqlcmd_url: "https://github.com/microsoft/go-sqlcmd/releases/download/v{{ sqlcmd_version }}/{{ sqlcmd_archive }}"
|
||||||
|
|
||||||
|
git_email: bartal@flo.fo
|
||||||
|
git_signing_key: "{{ user_home }}/.ssh/id_ed25519.pub"
|
||||||
Reference in New Issue
Block a user