Personal fresh-machine bootstrap for exactly two targets:
- Ubuntu 24.04 with Cinnamon
- Kubuntu 26.04 installed from its ISO with KDE Plasma
The steps below rebuild either machine; commands are run from the repository root unless stated otherwise.
sudo apt-get install -y git
git clone https://github.com/kuator/dotfiles.git "$HOME/dotfiles"
cd "$HOME/dotfiles"
./scripts/setup.shThis is the only automatic entry point. It rejects other Ubuntu release/desktop combinations before making changes, asks for sudo normally, installs the base APT packages and Zinit, links the tracked configuration, installs Mise-managed tools including Kanata and Bob's Neovim nightly, installs the subtitle synchronization tools used by mpv, and applies the tracked desktop keyboard settings. It is safe to rerun: an existing destination is moved to <name>-old, and setup stops rather than overwriting an existing backup.
Run every remaining command only after scripts/setup.sh succeeds.
Disable Snap before installing Firefox, then apply the remaining system and shell changes:
./scripts/optional/system/disable-snap.sh
./scripts/optional/shell/configure-bash-xdg.sh
./scripts/optional/shell/set-default-zsh.sh
./scripts/optional/system/configure-kanata.sh
./scripts/optional/system/configure-ssh-xdg.sh
./scripts/optional/system/disable-sudo-admin-flag.shThe final script applies the legacy home-marker fix on Ubuntu 24.04 and exits without changing anything under Kubuntu 26.04's sudo-rs.
Close every Codex process, then install Codex with its home under $XDG_DATA_HOME. The script also migrates an existing ~/.codex:
./scripts/optional/shell/install-codex.shInstall the Appgate Debian package before installing the XDG wrapper. For example, from the directory containing the package:
sudo dpkg -i AppGate-SDP-client.deb
cd "$HOME/dotfiles"
./scripts/optional/system/configure-appgate-xdg.shThe Appgate wrapper uses a private fake home under $XDG_DATA_HOME; the system service and running VPN client remain vendor software.
Appgate's Disconnect action removes the tunnel, routes, and DNS changes, but leaves the privileged appgatedriver.service running. To guarantee that no Appgate process remains active outside work hours, disable its automatic startup once:
sudo systemctl disable --now appgatedriver.serviceStart the driver immediately before using Appgate, then disconnect and quit Appgate before stopping it again:
sudo systemctl start appgatedriver.service
appgate
# After disconnecting and quitting Appgate:
sudo systemctl stop appgatedriver.serviceManual starts still work while the service is disabled. Confirm that the driver is stopped with:
systemctl is-active appgatedriver.service # expected: inactive
pgrep -x appgate-driver # expected: no outputAn Appgate package reinstall or upgrade may enable the service again; recheck it afterward.
Reboot before continuing. This activates the new login shell, Kanata group membership, system keyboard configuration, and any display-manager changes.
After logging in, configs/system/keyboard is the source of truth for layouts and switching. Cinnamon applies it through X11 and KDE derives its keyboard configuration from the same file.
Install the shared terminal font:
./scripts/optional/desktop/install-ubuntu-mono-nerd-font.shImport the GNOME Terminal profile, then apply the LightDM home-cleanup changes used by this machine:
./scripts/optional/desktop/import-gnome-terminal-profile.sh
./scripts/optional/desktop/lightdm/configure-xauthority.sh
./scripts/optional/desktop/lightdm/patch-binary.shUse Kubuntu's installed KDE terminal and display manager. Do not run the GNOME Terminal or LightDM scripts; the bootstrap has already written KDE's keyboard and repeat settings.
Install Firefox after Snap has been disabled:
./scripts/optional/firefox/install.shLaunch Firefox once so it creates a default profile, then close Firefox and run:
./scripts/optional/firefox/configure-profile.sh
./scripts/optional/firefox/patch-keybindings.sh
./scripts/optional/firefox/configure-new-tab.shInstall New Tab Override and Vimium through Firefox Add-ons. In New Tab Override, select Custom URL, enter http://127.0.0.1:8766/blank.html, and enable focusing the website instead of the address bar. In Vimium, set New tab URL to Browser's default new tab page. Firefox requires these extension changes to be made manually.
The new-tab service binds only to 127.0.0.1. Firefox updates replace omni.ja, so rerun firefox/patch-keybindings.sh after an update if the custom browser shortcuts stop working.
Install Valve's Steam package and the fixsteam fake-home launcher:
./scripts/optional/desktop/install-steam.shThe script preserves the existing library in $XDG_DATA_HOME/Steam and installs fixsteam under $XDG_DATA_HOME/fixsteam. Run steam once afterwards so fixsteam can create its fake home and desktop launcher. Steam remains outside the automatic bootstrap.
Install Anki, link mpv configuration, install mpvacious, and check the Anki add-on manifest:
./scripts/optional/japanese/setup.shPaste any printed codes into Anki → Tools → Add-ons → Get Add-ons, then restart Anki. After add-on 1045800357 exists, restore its optional 2.5 GiB local-audio collection:
./scripts/optional/japanese/download-yomitan-audio.shThe torrent and archive stay in ${XDG_CACHE_HOME:-$HOME/.cache}/dotfiles/yomitan-audio; the main bootstrap never starts this download.
The eight selected Yomitan dictionary ZIPs are carried directly in japanese/yomitan/dictionaries/. If an archive is missing, restore it from the manifest:
./scripts/optional/japanese/download-yomitan-dictionaries.shIn Yomitan, import the numbered archives from japanese/yomitan/dictionaries/, then import japanese/yomitan/settings.json from Settings → Backup → Import Settings. Follow japanese/yomitan/README.md to apply the tracked order to the currently selected profile.
Finally, start Anki with AnkiConnect enabled and update or create the official Japanese Sentences note type with the local compatibility changes:
./scripts/optional/japanese/update-japanese-sentences.shThe local template keeps images expanded on mobile, places them directly below the sentence on the answer side before definitions and notes, and presents Yomitan dictionary provenance as compact colored labels while retaining the full dictionary name in the card HTML and label tooltip. Restart Anki afterward so AJT Japanese refreshes its injected CSS and JavaScript.
Normal runs use a reviewed, pinned upstream commit. Check for upstream changes without modifying Anki, then explicitly test a reviewed commit if one is available:
./scripts/optional/japanese/update-japanese-sentences.sh --check-upstream
./scripts/optional/japanese/update-japanese-sentences.sh --upstream-ref <40-character-commit>The second command is a one-time override. After accepting the result, update upstream_ref near the top of the script so future normal runs keep that revision; otherwise, a normal run deliberately restores the existing pin.
The updater also maintains a local VocabFreq field, displayed as compact JPDB/CC100 labels on answer sides. Import the tracked Yomitan settings so newly mined notes fill it with {frequencies}.
To recover a missing book title on cards created from copied EPUB text, preview exact matches first, then apply the reviewed changes:
./scripts/optional/japanese/attribute-epub-cards.py ~/Books/book.epub
./scripts/optional/japanese/attribute-epub-cards.py ~/Books/book.epub --apply./tests/bootstrap.sh
nvim --version
mise doctor
test ! -e "$HOME/.appgate" && echo 'Appgate home is clean'On Ubuntu 24.04 Cinnamon/X11, also run setxkbmap -query. On Kubuntu 26.04, run kreadconfig6 --file kxkbrc --group Layout --key LayoutList. The first command above is the repository regression suite; the others are quick checks of installed tools and machine-level changes.
configs/home/profiledefines the login environment, XDG locations, and user-tool paths and is linked to~/.profile.configs/xdg/contains application configuration linked into$XDG_CONFIG_HOME, grouped by application. Notable exceptions handled specially by the linker are Codium's files and the globalty.toml.configs/system/keyboardis the single tracked source for the system, Cinnamon, KDE, IBus, and live X11 keyboard layout;configs/gnome-terminal/profile.dconfis imported rather than linked.docs/ergonomic-keyboard.mdrecords the ergonomic-keyboard requirements, shortlist, and current recommendation.docs/todo.mdtracks setup that still requires an external account or private recovery material.japanese/anki/addons.txtis the named AnkiWeb add-on manifest.japanese/yomitan/dictionaries.txt,japanese/yomitan/settings.json, andjapanese/yomitan/sort-dictionaries.jsdefine the selected dictionaries, exported settings, and active-profile order.japanese/anime/contains older subtitle timing tools and source-specific data; it is not part of bootstrap.
scripts/setup.shis the only entry point.scripts/bootstrap/install-packages.shinstalls Ubuntu packages.scripts/bootstrap/link-configs.shbacks up and links tracked configuration.scripts/bootstrap/install-mise.shinstalls Mise-managed CLI tools and Bob's Neovim nightly.scripts/bootstrap/install-subtitle-sync.shinstalls pinned ffsubsync through uv, alass-cli through the Mise-managed Rust toolchain, and autosubsync-mpv under mpv's scripts directory.scripts/bootstrap/configure-desktop.shderives desktop keyboard settings fromconfigs/system/keyboard.
Nothing under scripts/optional/ runs automatically. Several scripts use sudo, alter installed software, or require an application to be open or closed.
| Script | Purpose |
|---|---|
desktop/import-gnome-terminal-profile.sh |
Imports the tracked GNOME Terminal profile. |
desktop/install-steam.sh |
Installs Valve's Steam package and fixsteam fake-home launcher. |
desktop/install-ubuntu-mono-nerd-font.sh |
Downloads and installs UbuntuMono Nerd Font. |
desktop/lightdm/configure-xauthority.sh |
Stores LightDM Xauthority data outside the home root. |
desktop/lightdm/patch-binary.sh |
Patches LightDM to move .xsession-errors; use only with LightDM. |
firefox/configure-new-tab.sh |
Enables the localhost-only tracked new-tab page service. |
firefox/configure-profile.sh |
Links Firefox preferences and content CSS into its default profile. |
firefox/install.sh |
Installs Firefox from the Mozilla Team PPA. |
firefox/patch-keybindings.sh |
Rebuilds Firefox's omni.ja with the custom shortcuts. |
japanese/download-yomitan-audio.sh |
Downloads, caches, and installs the optional local-audio collection. |
japanese/download-yomitan-dictionaries.sh |
Restores missing dictionary archives from the tracked manifest. |
japanese/setup.sh |
Installs Anki and mpvacious and reports missing Anki add-ons. |
japanese/attribute-epub-cards.py |
Previews or restores EPUB book titles on matching Japanese Sentences notes. |
japanese/update-japanese-sentences.sh |
Fetches upstream Japanese Sentences, applies compatibility patches, and updates it through AnkiConnect. |
shell/configure-bash-xdg.sh |
Makes system Bash startup and history use XDG locations. |
shell/install-codex.sh |
Installs Codex through Mise-managed npm with an XDG data home and migrates an existing ~/.codex; Codex must be closed. |
shell/set-default-zsh.sh |
Interactively changes the login shell to Zsh. |
system/configure-appgate-xdg.sh |
Installs the Appgate fake-home wrapper with dpkg-divert. |
system/configure-kanata.sh |
Configures Linux groups, udev, and uinput, then enables the tracked Kanata user service. |
system/configure-ssh-xdg.sh |
Makes all OpenSSH clients use the tracked XDG config and migrates host keys. |
system/disable-snap.sh |
Removes Snap while preserving user data and prevents its reinstallation. |
system/disable-sudo-admin-flag.sh |
Prevents classic sudo from creating its home marker; safely does nothing under sudo-rs. |
bin/appgategives the vendor Appgate client a private fake home.bin/codiumlaunches VSCodium with its XDG data directory.bin/fdexposes Ubuntu'sfdfindexecutable under its upstreamfdname.bin/rgmakes ripgrep share the ignore file used by fd.bin/steamlaunches the optional fixsteam installation from its XDG data path.
tests/bootstrap.shchecks links, environment settings, desktop configuration, wrappers, migrations, and documented scripts.tests/python-environment.shchecks thevenv-based uv and ty project environment.tests/update-japanese-sentences.shexercises note-type download, patching, and AnkiConnect behavior with local fakes.tests/yomitan-sort-dictionaries.jschecks dictionary ordering without Yomitan.
japanese/anki/addons21/contains downloaded Anki add-ons and is intentionally ignored;japanese/anki/addons.txtis the reproducible source list.japanese/yomitan/dictionaries/contains the eight Git-tracked importable archives. Their internals are third-party data and are not documented here.configs/xdg/mpv/scripts/mpvacious/andconfigs/xdg/mpv/scripts/autosubsync-mpv/are ignored generated checkouts.japanese/setup.shinstalls a pinned commit from thekuator/mpvaciousfork, while the automatic bootstrap installs a pinned autosubsync-mpv commit and its ffsubsync and alass backends.
Put general declarative configuration under configs/ and Japanese study resources under japanese/. Put automatic fresh-machine work under scripts/bootstrap/ and call it from scripts/setup.sh; put destructive, optional, application-dependent, or machine-level work under the matching scripts/optional/ responsibility folder. Add a regression check when behavior—not just data—changes.