I get it. You SSH into your server and everything looks dull and gray. Or the colors are just wrong. It's annoying. Let me show you the fix that works 90% of the time.
The Quick Fix
- Check your TERM variable — SSH into your server and type this:
echo $TERM
If you see something like "xterm" or "vt100" or "linux" (without the "-256color" part), that's the problem. The terminal on your local machine (like your Mac's Terminal.app or Windows Terminal) expects a color-capable TERM value, but the remote server gives you a basic one.
- Force the TERM value — On your local machine, edit your SSH config file:
nano ~/.ssh/config
Add these lines at the top (or under the Host section for that server):
Host *
SetEnv TERM=xterm-256color
After you save and exit, try SSH again. You should see colors like you're used to locally. If not, move to the next step.
- Fix the remote .bashrc — SSH into the server, then open .bashrc:
nano ~/.bashrc
Look for lines that disable colors. Some servers have this at the top:
# force color off
case "$TERM" in
dumb|vt100)
export TERM=vt100
;;
esac
Delete those lines or comment them out with #. Then add this at the bottom of the file:
# Enable colors for ls and grep
alias ls='ls --color=auto'
alias grep='grep --color=auto'
# Set TERM if not already set
if [ -z "$SET_TERM" ]; then
export TERM=xterm-256color
export SET_TERM=1
fi
Save the file, then run source ~/.bashrc. Now type ls -la and you should see green, blue, yellow for files and folders. If you don't, the server might be using a different shell (like sh or dash). Check with echo $SHELL. If it's not bash, you need to edit .profile or .shrc instead.
Why This Happens
The TERM variable tells programs like ls, vim, and grep what the terminal can do. A value like "xterm-256color" says "I can show 256 colors and bold". But "vt100" says "I'm a dumb terminal from the 80s". The server often defaults to something safe (like vt100) because it doesn't know your local terminal supports colors.
Also, some Linux distributions (especially minimal servers or Docker containers) strip out color settings from .bashrc to save space. They assume you don't care about colors. You do care, so you need to put them back.
Another common trigger: you updated your local terminal emulator (like iTerm2 or Windows Terminal) and it started sending different TERM values. The old SSH session kept the old setting, so you see no colors. Always exit and re-SSH after changing local terminal settings.
Less Common Variations
1. Colors work locally but not through tmux or screen
If you use tmux (or screen) inside SSH, you need to tell tmux to pass the correct TERM. In your server's ~/.tmux.conf, add:
set -g default-terminal "screen-256color"
Then kill the tmux session and restart it: tmux kill-server, then tmux again. This works because tmux normally sets TERM to "screen" (no color support), but "screen-256color" enables 256 colors.
2. Colors look wrong (like red is weird or missing)
This happens when your local terminal expects one color profile, but the server sends another. For example, if your local terminal uses the "Solarized" theme, but the server's ls colors assume the default palette. The fix is to set the server's LS_COLORS to match your local theme. Or just use dircolors to generate a proper config:
dircolors -p > ~/.dircolors
Then edit ~/.dircolors and change the color codes to match your terminal's theme. This is advanced, so only do it if you really care about accurate colors.
3. No colors on Ubuntu Server 20.04 or 22.04 LTS
Ubuntu Server ships with .bashrc that disables colors if the TERM is "dumb" or "vt100". But it also has a bug: if you SSH from a terminal that sends TERM=xterm (not xterm-256color), Ubuntu's .bashrc thinks you can't handle colors and turns them off. The fix is the same as above — either set TERM to xterm-256color in your local SSH config, or edit the remote .bashrc to remove the color-blocking code.
How to Prevent This
Prevention is about consistency. Here's what I do for every new server I set up:
- Set TERM in SSH config — Add
SetEnv TERM=xterm-256colorto your local ~/.ssh/config for every host. This ensures you always send the right value, even if the server tries to override it. - Check .bashrc on first login — After SSHing in, run
cat ~/.bashrc | head -50. If you see any lines that check TERM and set it to something basic, delete them. - Use the same terminal everywhere — If you switch between iTerm2 on Mac, Windows Terminal on PC, and Konsole on Linux, they all send different TERM values. Standardize on one terminal emulator, or test your SSH config after each switch.
- Test with a simple command — After any change, run
echo -e '\e[32mGreen\e[0m'. If you see "Green" in green text, colors work. If you see raw escape codes (like ^[[32mGreen^[[0m), then TERM is wrong or the terminal isn't interpreting them.
That's it. You don't need to be a Linux guru to fix this. Just check TERM, fix .bashrc, and you're done. If you still have issues, post your echo $TERM output and the first 20 lines of your remote .bashrc in the comments. I'll help you sort it out.