How to install dotfiles safely and roll back

What a dotfiles install really changes on your system, how to preview it before anything happens, and how to undo it with backups and a rollback.

By Ny Harena RAVELOMANANTSOAUpdated Edit this page on GitHub

Installing someone else’s dotfiles is the quickest way to a good-looking Linux desktop, and the quickest way to lose your own setup. This guide explains what an install actually changes, how to see the plan before anything happens, and how to get back to where you were. It uses the installers generated by 0xTsoa as the example, but every step also applies when you install by hand.

What a dotfiles install actually changes

“Dotfiles” sounds like a few hidden files, but an install usually does up to four different kinds of thing, and each one is undone differently.

  1. Files in your home folder. Config folders copied into ~/.config, a cloned repository, a line added to ~/.bashrc. This is the part a backup can restore.
  2. Packages. 120 of the 163 installs in the registry add packages from your distro, and 70 use the Arch User Repository. Packages stay installed after you restore your files.
  3. The project’s own installer. 14 installs hand over to a script written by the project itself, such as ./setup.sh. That script decides what it touches, which can include your shell, your login screen and your bootloader.
  4. Changes outside your home folder. 3 installs use sudo for more than packages, for example to copy a theme into /usr/share.

Here is what that looks like for two real entries. The first only copies files:

The second runs the project’s own installer, which is common for complete Hyprland desktops:

Only 3 of the 163 installs in the registry are files only, so for almost every setup you need more than a file backup to get your system fully back. Every config page shows these facts under “At a glance” before you install anything.

Before you start: choose your safety net

Pick at least one of these. The more an install changes, the stronger the net you want.

A second user account. Create a user just for trying setups, log in to it from your login screen, and install there. Your own home folder is never touched. Packages are still installed for the whole system.

sudo useradd -m tryout
sudo passwd tryout

A virtual machine. The safest option for a complete desktop that runs its own installer. Some projects offer a live ISO you can boot in a VM before installing; ML4W does. Wayland compositors with animations, like Hyprland, usually need 3D acceleration enabled in the VM.

A system snapshot. On Btrfs, Snapper or Timeshift can take a snapshot of the system before you install, and roll back packages and system files afterwards. Both normally leave your home folder out: Timeshift excludes home folders by default, and Snapper’s root configuration does not include a separate home subvolume. So a snapshot covers what a file backup does not, and the other way round.

sudo timeshift --create --comments "before dotfiles"
# or, with Snapper:
sudo snapper -c root create --description "before dotfiles"

A copy of your config folders. The minimum, and enough for setups that only copy files. Copy the folders the setup writes to, or all of ~/.config:

cp -a ~/.config ~/config-backup-$(date +%F)

Read the plan before anything happens

Download the installer instead of piping it into a shell. A pipe runs code you have not read, and runs a truncated script if the download is cut off. Each config page shows the exact command:

curl -fsSLo install.sh https://www.0xtsoa.dev/configs/end-4/dots-hyprland/install.sh
less install.sh

If you have the GitHub CLI, you can also check that the file is the one built by 0xTsoa’s own workflow, not a modified copy:

gh attestation verify install.sh --repo nyharena25/0xTsoa --signer-workflow nyharena25/0xTsoa/.github/workflows/attest-installers.yml

Then ask for the plan. --dry-run writes nothing, installs nothing and never calls sudo:

bash install.sh --dry-run

Every line of the plan starts with a label:

Label Meaning
[download] The project’s source, fetched into a cache folder (~/.cache/0xtsoa).
[new] A file or folder that does not exist yet; it will be created.
[same] Already identical, or a package that is already installed; skipped.
[update] An existing clone of the same repository; backed up, then updated.
[append] A line added to a file, such as ~/.bashrc; the file is backed up first.
[conflict] Something different is already there; you are asked before it is replaced.
[package] Packages that are not installed yet, with your package manager and sudo.
[missing] Packages that cannot be installed on this system; the install stops before changing anything unless you pass --force.
[upstream] The project’s own installer, with the folders backed up before it runs.
[system] A sudo change outside your home folder, not undone by a rollback.
[reload] Asks your running compositor or desktop to reload. Nothing happens if you install from a TTY or another desktop; log in to see the changes.
[run] A command run as written, such as changing a setting.
[manual] A step you do yourself.

The summary at the end counts them and says what a rollback will and will not undo. If the plan shows something you do not expect, stop there: nothing has changed yet.

Install, and keep your own files

Run the script as your normal user, without sudo. It asks for sudo itself at the steps that need it, and refuses to run as root, because files written by root in your home folder can break your desktop.

bash install.sh

It shows the plan again and asks before doing anything. Then, before each change, it copies the file or folder it is about to change into a backup and checks the copy; if the backup fails, it stops before making the change. When a file already exists and differs, it asks you to keep yours (the default), replace it, or see the difference first.

If a package fails to install, the script still does the other steps, then ends with an error so you notice; scripts and CI that call it see the failure too.

Two options change that behaviour. --yes never asks, and still keeps your conflicting files. --force replaces them, after backing each one up. Use --force only when you have read the conflicts in the plan.

Undo it with --rollback

To go back, run the same script with --rollback:

bash install.sh --rollback

It lists what it will do and asks first:

  • files and folders that existed before are restored from the backup;
  • files and folders the install created are moved aside, not deleted;
  • packages and sudo changes are listed as kept, with the command that removes the packages this install added (packages you already had are never listed).

Backups live in ~/.local/state/0xtsoa/backups/ (one folder per setup, then one per install, named by date), with a copy of the script that made them. A rollback can itself be undone: whatever was in place before it is kept in that backup’s undone folder. Running --rollback again goes back one more install.

What a rollback does not undo:

  • Packages. The rollback prints the exact command, such as sudo pacman -Rns rofi; run it yourself once you are sure nothing else needs them.
  • Sudo changes and settings commands, such as files copied into /usr/share or a gsettings set. The plan marks them as [system] and [run]. A system snapshot taken before the install is the easy way back.
  • Whatever a project’s own installer writes outside the folders listed in the plan. For those setups, the backup covers the usual config folders (~/.config/hypr, ~/.config/waybar, ~/.zshrc and similar), not everything the script can reach. Read the project’s README for what else it changes, and prefer a second account or a VM.

Installing by hand instead

You do not need an installer at all. The safest manual install takes one part at a time:

  1. Read the project’s README and note every folder it asks you to copy.
  2. Back up those folders.
  3. Copy one folder, such as the bar config, restart that program, and check that it works.
  4. Move on to the next part only once the previous one does.

If you plan to keep and change the setup, put it under version control from day one. A dotfiles manager keeps your files in a Git repository and links or copies them into place, so going back is a git checkout away. GNU Stow links folders into place, chezmoi manages templates and differences between machines, yadm wraps Git around your home folder, and Dotbot and Dotter install from a config file.

A short checklist

  • Read what the setup changes: the “At a glance” panel on its page, or its README.
  • Pick a safety net: another account, a VM, a snapshot, or at least a copy of ~/.config.
  • Download the script, read it, and run --dry-run.
  • Install as your normal user, and keep your files when asked unless you mean to replace them.
  • Keep the backup until you are sure you like the new setup.

Ready to choose a setup? Compare complete dotfiles across window managers, or the best Hyprland dotfiles side by side.

Questions

Is it safe to run someone else's dotfiles install script?

Only once you know what it does. Read the script or its plan first, run it as your normal user rather than with sudo, and have a way back, such as a backup of your config folders or a system snapshot. A script that installs packages or runs its own installer changes more than your home folder.

How do I undo dotfiles I installed?

Restore your config folders from the backup you made before installing. If you used a 0xTsoa installer, run it again with --rollback to restore every file it changed in your home folder. Packages and system changes have to be removed by hand, or reverted with a system snapshot.

Will installing dotfiles overwrite my existing config?

Many install scripts replace folders in ~/.config without asking. The 0xTsoa installers keep any existing file that differs unless you choose to replace it, and back it up first when you do.

Do I need sudo to install dotfiles?

Copying config files never needs sudo, and running the whole script with sudo puts files in the wrong home folder or makes them owned by root. Only package installs and changes outside your home folder need it, and a good script asks for it at those steps only.