To create a symbolic link in Linux, use ln -s target linkname - the -s is what makes it symbolic. The order trips everyone up: the target (the real file) comes first, the link name second, the same order as cp and mv. The rule that prevents most broken-symlink pain: use an absolute path for the target. A symlink created with a relative target is resolved relative to the link’s location, not your current directory, so a relative target that looks right from where you are standing can point at nothing once you are elsewhere.
Table of contents
- The command and its argument order
- Use absolute paths for the target
- Symbolic links versus hard links
- Updating and overwriting a link
- Inspecting and removing links
- How this fits the rest of the stack
- FAQ
The command and its argument order
ln -s /path/to/target /path/to/linkname
-s makes it a symbolic link. The first argument is the target - the existing file or directory you are pointing at. The second is the link name - the new pointer you are creating.
The order is target first, link second, matching cp source dest and mv source dest. Getting it backwards is the most common mistake:
ln -s realfile.txt shortcut # shortcut -> realfile.txt (correct)
ln -s shortcut realfile.txt # oops, backwards
If you omit the link name, ln creates a link with the same basename as the target in your current directory:
ln -s /usr/local/bin/app # creates ./app -> /usr/local/bin/app
That shorthand is handy, but when you are learning, spell out both arguments so the direction is unambiguous. Target first, link second - say it to yourself while you type it.
Use absolute paths for the target
This is the rule that prevents most broken symlinks. A symlink stores the target path exactly as you typed it. If you type a relative path, it is later resolved relative to the link’s directory, not relative to where you were when you created it:
cd /home/sam
ln -s config.yaml /etc/app/config # target is the literal "config.yaml"
That link at /etc/app/config now points at config.yaml relative to /etc/app/ - which is /etc/app/config.yaml, not the file back in /home/sam. The link is broken, and it looked correct when you typed it.
Use an absolute target and the link works from anywhere:
ln -s /home/sam/config.yaml /etc/app/config # unambiguous
Relative targets do have legitimate uses - links inside a project that should stay valid when the whole project moves - but they require thinking about the link’s location, not yours. When in doubt, absolute. It is the single habit that eliminates most broken-symlink confusion.
Symbolic links versus hard links
ln without -s creates a hard link, which is a different thing:
- A symbolic link (
ln -s) is a small file containing a path to the target. It can point across filesystems, can link to directories, and breaks if the target is deleted or moved. - A hard link (
ln, no-s) is a second name for the same underlying data. It cannot cross filesystems, cannot link directories, and the data survives as long as any hard link to it exists.
ln -s target softlink # symbolic: a pointer to a path
ln target hardlink # hard: another name for the same data
For almost everything people mean by link - a shortcut, a version-independent name pointing at the current release, a convenient path to a file elsewhere - you want a symbolic link. Hard links are a lower-level tool with specific uses (deduplication, certain backup schemes). If you are not sure which you need, it is a symbolic link, which is why ln -s is the command in every how do I make a shortcut answer.
Updating and overwriting a link
By default ln refuses to overwrite an existing link, which is annoying when you want to repoint one:
ln -s /new/target mylink # fails if mylink exists
ln -sf /new/target mylink # -f forces the overwrite
-sf (symbolic + force) is the common combination for updating a symlink to point somewhere new. This is exactly how deployment schemes flip a current link between releases:
ln -sfn /releases/v2 /app/current # atomically repoint current to v2
The extra -n matters when the link points at a directory: without it, ln -sf would create the new link inside the existing directory the old link points to, rather than replacing the link. -sfn replaces the link itself. This current symlink flip is a classic zero-downtime deploy trick - the running app follows /app/current, and switching the link to a new release directory swaps versions instantly. Knowing -sfn is what makes that pattern reliable.
Inspecting and removing links
To see where a link points and whether it is valid:
ls -l mylink # shows mylink -> /path/to/target
readlink mylink # prints just the target path
readlink -f mylink # the fully resolved absolute target
ls -l shows the arrow and the target; a broken link often shows in red in a color terminal, which is a quick visual check. readlink -f resolves the whole chain to the real file, following links through links.
To remove a symlink, delete the link, not the target:
rm mylink # removes the link only, target is untouched
rm mylink deletes just the pointer; the real file it pointed at is unaffected. The one thing to be careful of: rm mylink/ with a trailing slash on a link to a directory can behave unexpectedly, and some tools follow the link. To delete a symlink cleanly, use its name with no trailing slash. Removing the link never removes the target - that separation is the whole point of a symbolic link.
How this fits the rest of the stack
The current-symlink flip is one of the oldest zero-downtime deploy tricks there is, and it teaches the idea a platform automates: switch what runs atomically, keep the old version around to roll back to. When deploys are managed for you, that atomic swap happens under the hood, but the mental model - point at the new release, keep the last one - is the same. The RunxBuild hosting calculator lays out the service, database, storage, and bandwidth as separate line items, and the RunxBuild dashboard is where the team watches deploys, logs, and restarts as they happen.
Useful related references:
- Create User in Postgres: The Right Way, the Lazy Way, and the Minimum Privilege Pattern That Survives Production
- create user postgres: The Commands That Work on Every Cluster and the Defaults That Bite You
- Ephemeral Environment: The PR-Preview Pattern, the On-Demand Spin-Up, the Cost, and the One That Actually Saves You Money
- Services on RunxBuild
FAQ
How do I create a symbolic link in Linux?
Use ln -s target linkname, where -s makes it symbolic, the target is the existing file, and the linkname is the new pointer. The order is target first, link second, matching cp and mv. Use an absolute path for the target to avoid broken links.
Why is my symbolic link broken?
Most likely you used a relative path for the target, which is resolved relative to the link’s own directory, not where you created it. A relative target that looks right from your current directory can point at nothing once the link lives elsewhere. Recreate it with an absolute target path.
What is the difference between a symbolic link and a hard link?
A symbolic link (ln -s) is a pointer to a path - it can cross filesystems, link directories, and breaks if the target moves. A hard link (ln, no -s) is another name for the same data, cannot cross filesystems or link directories, and keeps the data alive as long as it exists. Most shortcuts want a symbolic link.
How do I update a symbolic link to point somewhere else?
Use ln -sf newtarget linkname to force-overwrite an existing link, or ln -sfn when the link points at a directory so it replaces the link rather than creating one inside it. This is how deployment schemes atomically flip a current link between release directories.
How do I delete a symbolic link without deleting the target?
Run rm linkname - it removes only the link, leaving the target file untouched. Avoid a trailing slash on a link to a directory, since that can behave unexpectedly. Removing the link never removes the file it points to.