Exercise: Deploy Over SSH
Give the book club's server a short name in an SSH config file, then write deploy.sh, one command that checks the site, copies it to the server with rsync over SSH, lists what's live with ssh and can rehearse first, and let a check script that needs no server tell you what's done.
Freelancer · Unix · Linux · Updated
The Maple Street Book Club's website is a folder of four files, and it lives on a server called bookclub. Every time someone changes a page, somebody has to put it live: copy the right files to the right folder, remove the page the club took down, and check what's there now. Done by hand, one of those steps gets forgotten. You'll make it one command: give the server its short name in ssh-config, then write deploy.sh, which checks the site, copies it with rsync over SSH, lists what's live with ssh, and can rehearse first. A check script tells you what's done, and it needs no server at all.
Before you start
You need a terminal: the Terminal app on a Mac, or Ubuntu on Linux or in WSL on Windows. ssh and rsync are already there, and the check runs with bats, a small program that runs checks written for bash. If bats --version or rsync --version doesn't print a version number yet, install them:
sudo apt install bats rsync # Ubuntu, and Ubuntu in WSL
brew install bats-core # a Mac, with Homebrew
sudo asks for your password, the one you use to sign in; nothing shows on the screen while you type it.
Get the exercise code
Open this lesson's GitHub repository, github.com/ask-codey/exercise-bash-deploy-over-ssh, also linked from the Exercise box beside the lesson. Click Code, then Download ZIP, and unzip it into your terminal-practice folder. Or clone it with Git. On Windows, put it inside Ubuntu, in your Linux home folder, not in a Windows folder under /mnt/c, so chmod works on the scripts.
The folder holds:
site/: the book club's website, the pages you deploy.ssh-configanddeploy.sh: the two files you write. Each starts with a comment that says exactly what it must do.stand-in/ssh: a pretendssh, for trying your script on a computer with no SSH server.check.bats: the check. You don't need to change it.
What to do
Open a terminal in the exercise folder, make the scripts runnable (Your First Script), and open the first file in nano:
chmod +x deploy.sh stand-in/ssh
nano ssh-config
ssh-config: aHostblock that gives the namebookclubtheHostName localhost, your own user name asUser(whoamiprints it), and theIdentityFile ~/.ssh/id_ed25519. These are the lines for your~/.ssh/config.deploy.shcopies what's insidesite/into the folderbookclub-siteon the serverbookclub, withrsyncover SSH, so the server's copy matchessite/exactly: a page deleted fromsite/is deleted from the server too. Then it printsLive on bookclub:and the files inbookclub-siteon the server, by runninglsthere withssh.deploy.sh -nrehearses:rsynclists what it would copy and changes nothing, then the script printsRehearsal: nothing was copied.and stops with exit code 0.- No
site/index.html, no deploy. If it's missing,deploy.shsays so, copies nothing and stops with exit code 1, so an empty or wrongsite/can never replace the live site.
Try it as you go. With no SSH server, the stand-in runs every ssh command on your own computer, in the folder stand-in/server-home/; it's first on the PATH for this one command only (PATH: How a Command Is Found):
PATH="$PWD/stand-in:$PATH" ./deploy.sh -n
When every check passes, you can also deploy for real: see Optional: deploy to a real server below.
Check your work
From the exercise folder:
bats check.bats
At first almost every check fails. That's expected: each job you finish turns its checks into a ✓. The check reads ssh-config with your own ssh -G, which connects to nothing, and runs a copy of deploy.sh on a made-up garden club site of its own, in a throwaway folder, with its own stand-in ssh. A failing check says what to look at, for example about.html was deleted from site/, but it's still live on the server after the next deploy.
Hints
- Check the config before you trust it.
ssh -F ssh-config -G bookclubshows the settings ssh would use, as in SSH Keys and ~/.ssh/config. If it sayshostname bookclub, ssh didn't find yourHostblock. - Mind the slash and the colon. Copying Between Computers: scp and rsync shows what
site/andsiteeach copy, and what the colon inbookclub:bookclub-site/does. - Rehearse. The option that makes
rsynconly list what it would copy is the one you rehearsed with in Backups That Work: rsync.${1:-}is the first argument, or nothing when there isn't one. - Which computer fills it in? Running Commands on Another Computer shows which quotes let your script's
$folderreach the server already filled in. - Check first, copy second. Checking Before You Act: File Tests shows how to test that a file is there before anything else runs.
When you're done
Every check passes:
check.bats
✓ deploy.sh, ssh-config and site/ are here, and so are ssh and rsync
✓ 1) ssh-config gives bookclub the HostName localhost
✓ 2) ssh-config gives bookclub a User
✓ 3) ssh-config gives bookclub the key ~/.ssh/id_ed25519
✓ 4) deploy.sh copies what's inside site/ into bookclub-site on the server
✓ 5) deploy.sh connects to the short name bookclub
✓ 6) deploy.sh lists what's live on the server, with ssh
✓ 7) deploy.sh makes the server's copy match site/: a deleted page goes too
✓ 8) deploy.sh -n rehearses and changes nothing on the server
✓ 9) deploy.sh stops with exit code 1, and copies nothing, when site/index.html is missing
✓ 10) deploy.sh copies with rsync -a and --delete, and runs a command with ssh
11 tests, 0 failures
Now look back at deploy.sh. If the club moved its site to a new server tomorrow, which file would you change, and how many lines?
Optional: deploy to a real server
The stand-in pretends. A real SSH server shows you the whole trip, and your own computer can be that server, as in Logging In to Another Computer: ssh. This step is optional: the check and your submission don't need it.
Turning on an SSH server changes your computer: anyone who can reach it over the network can try to log in with your user name and password. Turn it on for this step, and off again when you're done.
Turn the SSH server on. On Ubuntu, and Ubuntu in WSL, install it, which also starts it. On a Mac, open System Settings, then General, then Sharing, and turn on Remote Login.
sudo apt install openssh-serverPut your key on it, as in SSH Keys and ~/.ssh/config. If
ls ~/.sshshows noid_ed25519, make one first withssh-keygen -t ed25519. Then hand its padlock to your own computer:ssh-copy-id "$(whoami)@localhost"Give
bookclubits name for real. Open~/.ssh/configin nano (it's a new, empty file if you don't have one yet), paste theHost bookclubblock from yourssh-configat the end, and save. Then try it:ssh bookclub lsshould list your home folder without asking for your computer's password. It may ask for your key's passphrase.Deploy. Rehearse first, then deploy, then look at what's live:
./deploy.sh -n ./deploy.sh ls ~/bookclub-siteThe four pages are now in
~/bookclub-site, copied there over SSH, as they would be on a server across the country. Delete a page fromsite/, deploy again, and watch it go from the live copy too.Tidy up. Turn the server off, and take the
Host bookclubblock out of~/.ssh/configif you won't use it again. On a Mac, turn Remote Login off in the same place.sudo apt remove openssh-server rm -r ~/bookclub-site
On a real server, only the Host block changes: its HostName, its User, and the key you put there. deploy.sh stays the same.
Submit your exercise
The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.
On GitHub, click +, then New repository. Name it (for example
exercise-bash-deploy-over-ssh), choose Public, and click Create repository. Leave out the README: your folder already has one.In a terminal in your exercise folder (Ubuntu in WSL on Windows), send your work to your new repo. If you downloaded the ZIP:
git init -b main git add . git commit -m "My solution" git remote add origin https://github.com/your-name/exercise-bash-deploy-over-ssh.git git push -u origin mainIf you cloned the starter instead, point your copy at your own repo, then commit and push:
git remote set-url origin https://github.com/your-name/exercise-bash-deploy-over-ssh.git git add . git commit -m "My solution" git push -u origin mainPaste your repo's address, such as
https://github.com/your-name/exercise-bash-deploy-over-ssh, into Submit your exercise on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.
Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.
So what
A deploy script is a checklist that can't skip a step: the same checks, the same copy and the same look at the result, every time, whether you run it or a scheduled job does.