How to Use Vim on a Linux VPS

15 min read·Matthieu·Server AdministrationSSHText EditorLinuxVim|

A practical Vim tutorial built around real server administration tasks. Learn modes, navigation, editing, search and replace, splits, .vimrc configuration, and workflows for editing Nginx, SSH, and Docker Compose files over SSH.

Vim is the default text editor on most Linux servers. When you SSH into a VPS to edit an Nginx config, change an SSH port, or tweak a Docker Compose file, Vim is what you get. This tutorial teaches Vim through real server administration tasks instead of abstract examples.

You will learn how Vim modes work, how to navigate and edit files efficiently, how to search and replace text, how to work with multiple files using splits and buffers, and how to set up a .vimrc that makes server work faster.

Prerequisites: A Linux VPS (Debian or Ubuntu) with SSH access Linux VPS Security: Threats, Layers, and Hardening Guide. Basic terminal familiarity (running commands, navigating directories).

How do I install Vim on Ubuntu or Debian?

Most Debian and Ubuntu servers ship with vim-tiny, a stripped-down build that lacks syntax highlighting, undo history, and plugin support. Install the full version to get all features covered in this tutorial.

sudo apt update && sudo apt install vim -y

Verify the installation:

vim --version | head -1

Expected output on Debian 12 (Bookworm):

VIM - Vi IMproved 9.0 (2022 Jun 28, compiled Nov 15 2023 17:28:07)

On Ubuntu 24.04 LTS, you will see Vim 9.1. The exact patch version varies by distribution, but all features in this tutorial work on Vim 8.2 and later.

What about Neovim? Neovim is a fork of Vim with a Lua-based config system and built-in LSP support. Everything in this tutorial applies to Neovim except the .vimrc path (Neovim uses ~/.config/nvim/init.vim). If you prefer Neovim, install it with sudo apt install neovim.

Start the built-in tutorial

Vim ships with an interactive tutorial that takes about 30 minutes. Run it before reading further if you have never used Vim:

vimtutor

This opens a practice file where you learn by doing. It covers the basics of movement and editing. The rest of this article goes deeper and adds server-specific workflows that vimtutor does not cover.

What are Vim modes and how do they work?

Vim has four main modes. Normal mode is the default. You use it for navigation and running commands. Insert mode is for typing text, entered with i. Visual mode selects text, entered with v. Command-line mode runs commands like save and quit, entered with :. Press Esc to return to normal mode from any other mode.

This is different from editors like nano where you type immediately. In Vim, keystrokes in normal mode are commands, not characters. This is called modal editing.

Mode Enter with Purpose Return to Normal
Normal Esc (or open a file) Navigate, delete, copy, paste, run commands Already in normal mode
Insert i, a, o, I, A, O Type and edit text Esc
Visual v (char), V (line), Ctrl+v (block) Select text for operations Esc
Command-line : Run ex commands (save, quit, search, replace) Enter or Esc

The mode indicator appears at the bottom left of the screen. When you see -- INSERT --, you are in insert mode. When nothing is shown, you are in normal mode.

If you feel stuck: press Esc two or three times. This always returns you to normal mode regardless of your current state.

How do I navigate files in Vim?

Navigation in Vim happens in normal mode. The basic movement keys are h (left), j (down), k (up), and l (right). Arrow keys also work, but hjkl keeps your fingers on the home row and is faster once you build muscle memory.

Character and line movement

Key Action
h Move left one character
j Move down one line
k Move up one line
l Move right one character
0 Jump to start of line
$ Jump to end of line
^ Jump to first non-blank character

Word movement

Key Action
w Jump to start of next word
b Jump back to start of previous word
e Jump to end of current word
W Jump to next WORD (whitespace-delimited)
B Jump back to previous WORD

File movement

Key Action
gg Go to first line of file
G Go to last line of file
42G or :42 Go to line 42
Ctrl+d Scroll down half a page
Ctrl+u Scroll up half a page
Ctrl+f Scroll down one full page
Ctrl+b Scroll up one full page
% Jump to matching bracket ((, {, [)

Search navigation

Press / to search forward, then type your search term and press Enter. Press n to jump to the next match and N to jump to the previous match. Press ? to search backward.

Example: you are editing /etc/nginx/nginx.conf and need to find the worker_connections directive:

/worker_connections

Vim jumps to the first match. Press n to cycle through all matches in the file.

How do I edit text in Vim?

Editing in Vim follows a pattern: operator + motion. The operator says what to do (delete, change, yank). The motion says what text to act on (word, line, paragraph). This composability is what makes Vim fast once you internalize a few building blocks.

Entering insert mode

Key Action
i Insert before cursor
a Append after cursor
I Insert at beginning of line
A Append at end of line
o Open new line below and enter insert mode
O Open new line above and enter insert mode

Delete, change, yank, and put

Command Action
x Delete character under cursor
dd Delete entire line
dw Delete from cursor to start of next word
d$ or D Delete from cursor to end of line
cc Change entire line (deletes and enters insert mode)
cw Change word (deletes word and enters insert mode)
ci" Change inside quotes (deletes text between " and enters insert mode)
yy Yank (copy) entire line
yw Yank word
p Put (paste) after cursor
P Put before cursor

Undo and redo

Key Action
u Undo last change
Ctrl+r Redo (undo the undo)
. Repeat last change

The . (dot) command is one of Vim's most useful features. It repeats whatever you last did. Change a word with cw, type the replacement, press Esc. Now move to another word and press . to make the same change.

Server-relevant editing examples

Delete a directive from an Nginx config: Position your cursor on the line access_log /var/log/nginx/access.log; and press dd to delete the entire line.

Change a port number in quotes: Position your cursor anywhere inside "8080" in a Docker Compose file and press ci". This deletes 8080 and puts you in insert mode. Type 3000 and press Esc.

Delete two words from a directive: Press d2w to delete the next two words from the cursor position. Vim commands accept a count before the motion: 3dd deletes three lines, 5j moves down five lines.

How do I search and replace text in Vim?

Use :s (substitute) to replace text. The basic syntax is :s/old/new/flags. This command works on the current line by default. Use :%s to apply it to the entire file.

Substitute patterns

Command Action
:s/foo/bar/ Replace first foo with bar on current line
:s/foo/bar/g Replace all foo with bar on current line
:%s/foo/bar/g Replace all foo with bar in entire file
:%s/foo/bar/gc Replace all with confirmation (y/n for each match)
:5,10s/foo/bar/g Replace all on lines 5 through 10

Practical examples

Change the Nginx listen port from 80 to 443:

:%s/listen 80;/listen 443 ssl;/g

Comment out a line in sshd_config: Move to the line and press I to insert at the beginning, type #, press Esc.

Comment out multiple lines: Select lines with V (visual line mode), move down with j to extend the selection, then type :s/^/#/ and press Enter. This prepends # to each selected line.

Replace a Docker image tag:

:%s/nginx:1.24/nginx:1.27/g

Regex basics in Vim substitute

Vim uses its own regex flavor. A few patterns you will use often on server configs:

Pattern Matches
^ Start of line
$ End of line
. Any single character
\d A digit (0-9)
.* Any characters (greedy)
\s Whitespace

To match literal dots (like in IP addresses), escape them: :%s/192\.168\.1\.1/10.0.0.1/g.

How do I edit multiple files in Vim with splits and buffers?

Vim can open multiple files in a single session using buffers, split windows, and tabs. This is useful when you need to cross-reference files while editing, like checking nginx.conf while editing a site-specific server block.

Buffers

A buffer is a file loaded into memory. You can have many buffers open and switch between them.

Command Action
:e /etc/nginx/sites-available/default Open file in new buffer
:bn Switch to next buffer
:bp Switch to previous buffer
:ls List all open buffers
:b2 Switch to buffer number 2
:bd Close current buffer

Split windows

Splits let you see two files side by side in the same terminal.

Command Action
:sp /path/to/file Horizontal split (top/bottom)
:vs /path/to/file Vertical split (left/right)
Ctrl+w h/j/k/l Move between splits (left/down/up/right)
Ctrl+w = Make all splits equal size
Ctrl+w q Close current split

Example workflow: edit a Docker Compose file while referencing the .env file:

:e docker-compose.yml
:vs .env

You now have two panes. Use Ctrl+w l and Ctrl+w h to switch between them.

Tabs

Tabs are collections of windows. Most people find splits sufficient for server work, but tabs are available:

Command Action
:tabnew /path/to/file Open file in new tab
gt Go to next tab
gT Go to previous tab
:tabclose Close current tab

How do I customize Vim with a .vimrc file?

The .vimrc file in your home directory controls Vim's behavior. Without it, Vim runs in a near-compatible Vi mode that lacks many features. A good .vimrc tuned for server work makes editing config files faster.

Create or edit your .vimrc:

vim ~/.vimrc

Add these settings. Each line has a comment explaining what it does:

" Disable Vi compatibility mode (enable all Vim features)
set nocompatible

" Use UTF-8 encoding (required for special characters in listchars on minimal server images)
set encoding=utf-8

" Show line numbers (essential for config files with error messages referencing line numbers)
set number

" Show relative line numbers (makes jumping N lines easy: 5j, 12k)
set relativenumber

" Enable syntax highlighting
syntax on

" Use spaces instead of tabs (most config files expect spaces)
set expandtab

" Set tab width to 2 spaces (common for YAML, Nginx configs)
set tabstop=2
set shiftwidth=2
set softtabstop=2

" Highlight search results as you type
set incsearch
set hlsearch

" Case-insensitive search unless uppercase is used
set ignorecase
set smartcase

" Show matching brackets
set showmatch

" Always show the status line (shows filename and position)
set laststatus=2

" Enable mouse support (useful in modern terminals)
set mouse=a

" Show current mode in status line
set showmode

" Set pastetoggle to F2 (toggle paste mode for clean pasting over SSH)
set pastetoggle=<F2>

" Disable swap files (avoids .swp clutter on servers)
set noswapfile

" Enable filetype detection (loads correct indentation for yaml, json, etc.)
filetype plugin indent on

" Highlight the current line
set cursorline

" Show whitespace characters (catch trailing spaces and mixed indentation)
set list
set listchars=tab:»·,trail:·

Save and exit with :wq. The settings take effect the next time you open Vim.

To reload your .vimrc without restarting Vim:

:source ~/.vimrc

Paste mode for SSH sessions

When you paste text from your local clipboard into Vim over SSH, auto-indentation can create a cascading indent effect where each line shifts further right. This happens because Vim treats pasted text as typed input and applies indent rules to each line.

Toggle paste mode before pasting:

  1. Press F2 (if you set pastetoggle as shown above) or type :set paste
  2. Enter insert mode with i
  3. Paste your text (Ctrl+Shift+V or right-click in your terminal)
  4. Press F2 again or type :set nopaste

Modern terminals with Vim 8.2+ support bracketed paste mode, which handles this automatically. If you use a recent terminal emulator (kitty, Alacritty, WezTerm, recent GNOME Terminal), paste mode toggling may not be necessary.

How do I add plugins with vim-plug?

vim-plug is a lightweight plugin manager that installs plugins in parallel. It requires a single file download and a few lines in your .vimrc.

Install vim-plug

curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

Verify the file exists:

ls -la ~/.vim/autoload/plug.vim

You should see the file with your user ownership.

Configure plugins in .vimrc

Add a plugin block to the top of your ~/.vimrc, before the settings:

call plug#begin('~/.vim/plugged')

" File explorer sidebar
Plug 'preservim/nerdtree'

" Fuzzy file finder
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'

" Git status indicators in the gutter
Plug 'airblade/vim-gitgutter'

call plug#end()

Save the file, then install the plugins:

:source ~/.vimrc
:PlugInstall

vim-plug downloads each plugin in parallel. After installation, you can open NERDTree with :NERDTree, use :Files to fuzzy-find files, and see git diff markers in the gutter.

Keep it minimal on servers. Plugins add startup time. On a VPS where you edit config files occasionally, three to five plugins is plenty. Save heavier setups for your local development machine.

How do I edit server config files with Vim over SSH?

This section covers workflows you will use repeatedly when managing a VPS. Each example uses a real file and shows the exact steps.

Use sudoedit instead of sudo vim

When editing root-owned files like /etc/nginx/nginx.conf or /etc/ssh/sshd_config, use sudoedit instead of sudo vim.

sudoedit /etc/nginx/nginx.conf

sudoedit copies the file to a temporary location, opens it with your user's Vim (including your .vimrc settings and plugins), then copies it back with root permissions when you save and quit. This is safer than sudo vim for two reasons:

  1. sudo vim runs Vim as root. Any Vim command like :!bash spawns a root shell. On multi-user servers this is a privilege escalation risk.
  2. sudoedit preserves your user environment. You get your syntax highlighting, line numbers, and keybindings.

Edit an Nginx server block

Open the default site configuration:

sudoedit /etc/nginx/sites-available/default

Find the server_name directive by typing /server_name and pressing Enter. Vim jumps to the match. Press cw to change the word after the directive, type your domain, press Esc.

After saving, verify the Nginx config syntax:

sudo nginx -t

Expected output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Then reload:

sudo systemctl reload nginx

Change the SSH port in sshd_config

sudoedit /etc/ssh/sshd_config

Search for the port directive:

/^#\?Port

This regex matches both Port and #Port (commented out). If the line is commented, press 0 to go to the start of the line, press x to delete the #, then press f followed by a space to jump to the space before the port number. Press cw, type the new port number (for example 2222), and press Esc.

Verify the config:

sudo sshd -t

No output means the syntax is valid. Restart the service:

sudo systemctl restart sshd

Before disconnecting, open a second SSH session on the new port to verify you can still connect. Losing SSH access by changing the port without testing is a common mistake Linux VPS Security: Threats, Layers, and Hardening Guide.

Edit a Docker Compose file

vim ~/myapp/docker-compose.yml

YAML files are indentation-sensitive. The .vimrc settings from earlier (2-space tabs, expandtab) handle this correctly. If you see tab characters in a YAML file, convert them:

:%s/\t/  /g

This replaces all tabs with two spaces. Save and validate the file:

docker compose config --quiet

No output means the YAML is valid. If there is a syntax error, Docker Compose prints the line number. Jump directly to that line in Vim with vim +42 docker-compose.yml (where 42 is the error line).

Edit a systemd unit file

sudoedit /etc/systemd/system/myapp.service

After saving changes to a systemd unit, reload the daemon:

sudo systemctl daemon-reload

Then restart the service and verify:

sudo systemctl restart myapp
sudo systemctl status myapp

Sharp eyes: check the Active: line in the status output. It should show active (running). If it shows failed, read the logs:

journalctl -u myapp -n 20 --no-pager

Vim survival cheatsheet

The ten commands you need on day one:

Command Action
i Enter insert mode
Esc Return to normal mode
:wq Save and quit
:q! Quit without saving
dd Delete line
u Undo
/text Search forward
:%s/old/new/g Replace all in file
:sp file Split window
F2 Toggle paste mode

For the complete reference with navigation, editing, visual mode, buffers, splits, regex patterns, and server workflow shortcuts, see Vim Cheatsheet.

Something went wrong?

Vim opened and I cannot type. You are in normal mode. Press i to enter insert mode.

I see -- INSERT -- but my keystrokes do weird things. You may have accidentally pressed Ctrl+s, which freezes terminal output. Press Ctrl+q to unfreeze.

My pasted text has staircase indentation. Toggle paste mode with F2 or :set paste before pasting. Remember to turn it off after: F2 again or :set nopaste.

Vim says "E45: 'readonly' option is set." The file is read-only. Quit with :q and reopen with sudoedit /path/to/file.

I made a mistake and saved. If the file is a system config, Vim may have left a backup. Check for filename~ in the same directory. You can also undo after reopening if you set set undofile and set undodir=~/.vim/undodir in your .vimrc (create the directory first with mkdir -p ~/.vim/undodir).

Swap file warning: ".file.swp" already exists. A previous Vim session crashed or is still open. If no other session is editing the file, choose (D)elete to remove the swap file. If you disabled swap files in your .vimrc (set noswapfile), this will not happen.


Next steps: Pair Vim with a terminal multiplexer so your editing sessions survive disconnections. See How to Use tmux on a Linux VPS for tmux or How to Use GNU Screen on a Linux VPS for GNU Screen. For the Nginx configuration examples in this article, see the full guide at Nginx Administration on a VPS.


Copyright 2026 Virtua.Cloud. All rights reserved. This content is original work by the Virtua.Cloud team. Reproduction, republication, or redistribution without written permission is prohibited.

Ready to try it yourself?

Deploy your own server in seconds. Linux, Windows, or FreeBSD.

See VPS Plans