I kind of wrote this specifically for Jimmey, one of the not-so-fullstack-developers where I work. I do all my v2+ pushes using symlinks, and he's super-curious about symlink deploys because they go so smoothly, but when he googles all he can find is hacker stuff.
Info on symlink deploys should be far more accessible than that, because it's a really simple - albeit not exactly SOP - topic, and it's a huge entry-point to the world of CI\CD, and really devops in general.
So I wrote this - for Jimmey - so he would always know where to find a solid step-by-step for moving a production site to symlink deploy.
...you're welcome, Jimmey ;)
Symlink deployment is a strange word if you're not living in the linux world. If you are… you know what symlinks are, and you love them. For the Windows crowd: symlinks are… let's say they let one file/folder pretend to be another. Windows has links, and they let you jump to another place a lot like a web link works. Symlinks behave very differently. They have the content of the target, but the path is unchanged. It's a little more like a rewrite rule, I guess you'd say.
Linux people use them a lot for installing apps. Say I have Awesome App v2 and it's AWESOME. version 3 comes out and it's AWFUL.
Without symlinks, that's unfortunate.
With symlinks, though:
- I installed v2 as a symlink that looks like
awesomeapp -> awesomeappv2
- My executable is just
- I installed v3 as
awesomeapp -> awesomeappv3
The command didn't change, but the app did.
When it turns out v3 is awful, i type 4 words and the symlink points back to v2.
Why this is relevant to what we're doing: deploying a new version of a live site can be scary. Maybe it hasn't been tested in its final environment, so you can only be so sure. Maybe there's downtime or cutover to worry about, so higher-ups want you to do it at midnight on Friday (and test all Saturday, with a tentative switchback on Sunday).
With symlinks: nope.
- You get a grace period where both versions are live in the final hosting. Great for last-round checks.
- The user facing cutover happens in 3-4 milliseconds, so downtime is a non-issue.
- The older version doesn't get destroyed, so it's always there for legacy reference - unless you decide to remove it.
Sounds magical, right?!?! Unfortunately, if you're like most of the world that's hosting through whm on CentOS or RHEL, this isn't the default config. Why, is beyond me. Fortunately, it's harmless and simple to switch your VHost to symlink.
The famous WHM+Apache+CentOS that you should already be familiar with has a directory structure that sends user traffic to the current site version along this path:
www -(symlink)-> public_html <files>
We'll shuffle that juuuust a little, so it follows a path more like
www -(symlink)-> public_html -(symlink)-> site_versions/v1 <files>
Then when we cutover, it's just a question of flipping the
public_html symlink to point to
As a bonus, we'll be co-hosting the two versions - without symlinks - directly from those directories. This way, we have site.com (public), and we also have v2.site.com and v1.site.com for (respectively) prelaunch testing and postlaunch reference.
1. Convert to Symlinks
Fair warning: I've done this hundreds and hundreds of times, and no problems. But
rm -rf public_htmlstill feels so unnatural. It'll never feel right.
ln -s source target, note the the source folder name doesn't have a trailing slash. This sort of hints at super-low-level "How filesystems work" - which isn't for this post. For now, suffice it to say: "Just don't use trailing slashes when creating\deleting symlinks".
su $acctname #puts us in /home/acctname with the right permissions mkdir site_versions # make the new parent directory cp -r public_html site_versions/v1 # copy the current site files the the v1 dir rm -rf public_html # destroy public_html (the unnatural part) ln -s site_versions/v1 public_html # make a symlink from v1 to public_html, restoring the chain
Now you're symlinked. Whoohoo! Your site's still good, but it's running from
2. Make Subdomains
Setup a subdomain through the usual cpanel/whm route that points to
site_versions/v1 and your legacy reference is done.
Setup another subdomain that points to
3. Push the new code
Move your new site code to the
site_versions/v2 directory. You've already setup a subdomain there, so you can testtesttest at v2.site.com.
rm -f public_html ln -s site_versions/v2 public_html
Done. You're live. Easy, right?
If it turns out tomorrow that there IS a critical bug in v2, it's just as easy to run those last commands to point
site_versions/v1 while you work it out. Run
rm -rf public_html ln -s site_versions/v1 public_html
And now your public site is v1, but you can work on v2.site.com right beside it.