A link lets one file or directory be reached through another path. Linux has two kinds, and ln creates both. Symlinks in particular are everywhere on servers: Nginx’s sites-enabled, versioned releases, shared config files.

ln -s TARGET LINK_NAME
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
ln -s /var/www/releases/2026-11-04 /var/www/current

A symlink is a small file that contains a path. Opening the link opens the target. ls -l shows where it points:

lrwxrwxrwx 1 root root 39 Nov  4 10:00 example.com -> /etc/nginx/sites-available/example.com

Remember the order: target first, link second — the same order as cp.

Relative vs absolute targets

cd /var/www
ln -s releases/2026-11-04 current       # relative: resolved from the link's own directory
ln -s /var/www/releases/2026-11-04 current   # absolute

Relative symlinks keep working if you move the whole directory tree (or mount it elsewhere, e.g. in a container). Absolute ones are clearer when the link and target live far apart.

ln TARGET LINK_NAME

A hard link is a second name for the same file (the same inode). Both names are equal; there’s no “original”. Data is freed only when the last name is removed.

ln report.txt report-copy.txt
ls -li report*      # same inode number, link count 2
Symbolic link Hard link
Points to A path The same inode (data)
Directories Yes No
Across filesystems Yes No
If the target is deleted Link breaks (“dangling”) Data remains reachable
Shows in ls -l link -> target Looks like a normal file
Typical use Configs, releases, shortcuts Backups with deduplication (rsync --link-dest)

In day-to-day server work you’ll almost always want symlinks.

ln -s fails if the link already exists. Use -f (force) — and for links to directories, -n so ln replaces the link instead of creating a new link inside the target directory:

ln -sfn /var/www/releases/2026-11-05 /var/www/current

This one-liner is the heart of zero-downtime deployments: build the new release in its own directory, then switch the current symlink atomically. Rolling back is the same command with the previous release.

ls -l link
readlink link            # the stored target
readlink -f link         # fully resolved absolute path
realpath link
stat link
find /etc/nginx/sites-enabled -xtype l
find / -xdev -xtype l 2>/dev/null

-xtype l matches symlinks whose target doesn’t exist. Delete them with -delete after reviewing the list.

rm link
unlink link

Careful with trailing slashes on directory symlinks: rm link removes the link; rm -r link/ may follow it and delete the contents of the target. Never add a trailing slash when removing a symlink.

Permissions and ownership

Symlinks always show lrwxrwxrwx; access is decided by the target’s permissions. Change the owner of the link itself (rarely needed) with chown -h. Some services restrict following symlinks for security — Nginx’s disable_symlinks, Apache’s Options FollowSymLinks/SymLinksIfOwnerMatch.

Common uses on servers

  • Enable sites/modules: sites-enabled → sites-available (Nginx, Apache).
  • Releases: /var/www/current → the active release directory.
  • Shared data across releases: releases/X/storage → /var/www/shared/storage.
  • Version switching: /usr/local/bin/node → a specific Node version.
  • Moving data to another disk: move /var/lib/app to /srv/app, then ln -s /srv/app /var/lib/app (stop the service first).

Quick reference

Task Command
Symlink ln -s target link
Replace a symlink ln -sfn target link
Hard link ln target link
Where does it point? readlink -f link
Broken links find DIR -xtype l
Remove rm link (no trailing slash)

Related: Linux file permissions and Nginx server blocks.

  • Linux
  • Command Line
  • Filesystem