How to Change the Default Shell on Fedora (Bash, Zsh, Fish)

To change your default shell on Fedora, first install the desired shell package using `dnf`, then add it to the `/etc/shells` whitelist, and finally update your user record with `chsh`.

The terminal opens and Bash stares back

You open a new terminal window. Bash loads its default prompt. You installed Zsh three days ago because every tutorial promised better autocompletion and syntax highlighting. The terminal ignores it. You type zsh manually, get the fancy prompt, close the window, and open a new one. Bash is back. You are stuck in a loop of manual overrides. The system is not broken. It is just waiting for you to tell it which program should run when a login session starts.

What the system actually tracks

Linux does not guess your preferences. Every user account has a single field in the password database that points to an executable. That field is the login shell. When you authenticate via SSH, press Ctrl+Alt+F3 for a TTY, or open a terminal emulator configured for login sessions, the PAM stack reads that field and executes the binary. If the binary is not in the approved list, the system blocks it for security reasons. Think of /etc/shells as a building access list. The door will not open for anyone not on the roster, even if they have a keycard. Changing your default shell is just updating that roster and pointing your user record to the new binary.

The seventh field in /etc/passwd holds this path. The Name Service Switch (NSS) reads it every time a session initializes. Display managers, SSH daemons, and terminal emulators all query NSS before spawning your interactive environment. If the path is missing or points to a non-executable file, authentication fails or falls back to /bin/sh. Fedora enforces strict path validation to prevent privilege escalation through malicious shell replacements.

Run getent passwd to see how the database structures user records. Each line contains seven colon-separated fields. The last field is your login shell. The system trusts this value implicitly during session startup. Trust the package manager. Manual file edits drift, snapshots stay.

Install and register the new shell

Fedora ships with Bash compiled into the base system. Zsh and Fish live in the standard repositories but require explicit installation. Run the package manager first.

sudo dnf install zsh fish
# Pulls the latest stable binaries from Fedora's primary repository
# Installs both shells so you can test them before committing
# dnf resolves dependencies automatically and locks the transaction

After installation, verify the binary path. Fedora places most command-line tools in /usr/bin/. Older systems used /bin/, but modern Fedora uses a unified /usr/bin/ via symlinks. The path must be exact.

which zsh
# Returns the absolute path the system will use to execute the binary
# Confirms the package installed correctly and is in your PATH
# You will need this exact string for the next step

Next, check the whitelist. The /etc/shells file contains one valid shell path per line. If your new shell is missing, chsh will refuse to update your account.

cat /etc/shells
# Displays the current list of approved login shells
# Look for /usr/bin/zsh or /usr/bin/fish in the output
# If missing, the system considers the binary unsafe for authentication

If the path is absent, append it. Do not edit the file with a text editor unless you know how to preserve permissions. Use tee to append safely.

echo "/usr/bin/zsh" | sudo tee -a /etc/shells
# Appends the path to the end of the whitelist file
# sudo grants the necessary root privileges for /etc/ modifications
# tee writes to the file and prints the result to confirm success

Convention aside: /etc/ holds user-modified configuration. /usr/lib/ ships with packages. Never edit files in /usr/lib/ directly. Fedora's update process will overwrite them on the next dnf upgrade --refresh. Keep your customizations in /etc/ or your home directory.

Switch the login shell

Now update your user record. The chsh command modifies the seventh field in /etc/passwd. This field tells PAM and your display manager which program to launch after authentication.

chsh -s /usr/bin/zsh
# Changes the login shell for the currently active user
# The -s flag specifies the new shell path explicitly
# Updates /etc/passwd without requiring a full reboot

Log out of your desktop session and log back in. Terminal emulators like GNOME Terminal or Konsole inherit the shell setting from your user record. If you are using a TTY, switch to another virtual console and back. If you are connecting via SSH, close the connection and reconnect. The new shell will load automatically.

Reboot before you debug. Half the time the symptom is gone.

Verify the change took effect

Do not guess. Check the database directly.

getent passwd $USER
# Queries the Name Service Switch for your user record
# The last field shows the currently assigned login shell
# Confirms chsh wrote the correct path to the system database

Run echo $SHELL inside the new terminal. It should match the path you just set. If it still shows /bin/bash, your terminal emulator is overriding the login shell. Check the profile settings in your terminal application and disable any custom command overrides. Some emulators cache the shell path in their own configuration files. Clear the cache or restart the emulator process entirely.

Run ps -p $$ -o comm= to verify the actual process running your current session. The output must match your new shell. If it does not, your terminal is spawning a non-login shell that ignores the /etc/passwd setting. Configure your terminal to run a login shell, or add an explicit shell invocation to your terminal profile.

Common pitfalls and error messages

The most common error happens when the path in /etc/shells does not match the path you pass to chsh. The command will print a clear refusal.

chsh: /usr/local/bin/zsh: invalid shell

This error means the binary exists but is not whitelisted. Add the exact path to /etc/shells and try again. Do not force the change with vipw unless you understand the password file format. Manual edits corrupt user records faster than they fix them.

Another trap involves configuration files. Switching shells does not migrate your Bash history or aliases. Zsh expects ~/.zshrc. Fish expects ~/.config/fish/config.fish. If the files are missing, the shell loads with factory defaults. Create them before you commit to the switch. Copy your essential environment variables and PATH modifications manually. Do not symlink ~/.bashrc to ~/.zshrc. The syntax differs enough to break your session.

Cron jobs and systemd user services also read the login shell field. If you switch to Fish, a cron job that relies on Bash array syntax will fail silently. Check your scheduled tasks and add an explicit #!/usr/bin/bash shebang to any script that depends on specific shell features. The system will respect the shebang regardless of your default login shell.

Non-login shells behave differently. When you run bash or zsh from within an existing terminal, you start a non-login shell. Non-login shells skip /etc/profile and ~/.bash_profile. They read ~/.bashrc or ~/.zshrc instead. This is why your new shell looks different when launched manually versus when it starts a session. Understand the initialization order before you spend hours debugging missing aliases.

Run journalctl first. Read the actual error before guessing.

Pick the right shell for your workflow

Use Bash when you need maximum compatibility with legacy scripts and server documentation. Use Zsh when you want advanced autocompletion, syntax highlighting, and a plugin ecosystem without leaving the POSIX family. Use Fish when you prefer modern defaults like syntax highlighting out of the box and do not mind a different scripting syntax. Stick with the default Bash if you only open the terminal occasionally and value stability over features.

Where to go next