AMP stack script on Ubuntu
This article is about several things:
- shell scripting with bash
- using GitHub Actions
- developing a re-usable script to prepare an Ubuntu server (or Docker container) to run Moodle.
Requirements
- A single bash script
- Use functions for better programming style
- Support installing just a few options with switches
- Make script idempotent - to re-run without failing
Environment
- Use a public GitHub repository
- to be useful to others
- to force me to use good coding style, and check in GitHub version control to code in the open, and also because Actions is free for the 40 million developers on GitHub to use with public repositories
- Use GitHub actions to lint the script
- Use GitHub actions to quickly test whether the code works (option for an ubuntu-20.04 agent, which corresponds to the desired server, and also because I'm using Ubuntu 20.04 on Windows Subsystem for Linux 2).
Script use cases
- Install Apache
- Install PHP
- Install PHP-FPM
- Install php-mysql module
- Install Memcached
- Set up virtual hosts with SSL certificates (even if self-signed)
- Backup script for code and databases - local destination, and then synced to AWS S3
Set up GitHub repository
- Sign in to GitHub with my personal account
- Create a new repository - [nickromney/amp-moodle], with description "Install AMP stack on Ubuntu, with optional Moodle"
- Added a README
- Left default branch with the new default of
main
- Under
Code
, chooseClone
, andSSH
- Copy
git@github.com:nickromney/amp-moodle.git
- Open a terminal (for me, ZSH on WSL2 running Ubuntu 20.04)
- Change the domain to
personal.github.com
to prompt for my personal SSH key while I clone the repository locally git clone git@personal.github.com:nickromney/amp-moodle.git
Set up GitHub actions and linting
- Check what default software is available on the Ubuntu 20.04.1 LTS virtual environment. We see that there's already some software which could speed us up:
- curl
- git
- unzip
- wget
- AWS CLI
- PHP 7.4.13
- Google Chrome and ChromeDriver
- PostgreSQL
- MySQL 8.0.22
- MySQL Server
- And installed apt packages:
- dnsutil
- shellcheck
Set up ShellCheck
- Read about ShellCheck on David Jeddy's blog
- Read the linked article by Nick Janetakis on quoting variables
- Install the recommended VS Code extension
- Find that there's a GitHub Action for Shellcheck
Create a GitHub workflow to lint with ShellCheck
cd amp-moodle
git checkout -b add-linting-workflow
- In VSCode, add
.github/workflows/lint.yml
, and adapt the example from GitHub Action for Shellcheck, because we want to:- lint all branches except
main
(we want to protect the main branch, and ensure we only merge intomain
via Pull Requests) - specifically use the Ubuntu 20.04 image (by choosing
runs-on: ubuntu-20.04
rather thanruns-on: ubuntu-latest
)
- lint all branches except
name: Lint
on:
push:
branches:
- '**'
- '!main'
jobs:
shellcheck:
name: Shellcheck
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
This runs a workflow of two actions
- checks out the code
- runs shellcheck against matching files
git add .github/
git commit -m "Add linting workflow"
git push --set-upstream origin add-linting-workflow
Now we're in a position to merge the lint check to main, and then write a shell script.
- Create Pull Request
- Merge
- Delete
add-linting-workflow
branch from GitHub
##
git checkout main
git fetch origin
git reset --hard origin/main
And I see
HEAD is now at 6b8e12b Merge pull request #1 from nickromney/add-linting-workflow
Run the script on merges to main
Then we need to actually run our amp.sh
script (which we are yet to write) on merges to main
For this, we'll need an additional workflow
git checkout main
git checkout -b add-ci-workflow
Create .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
jobs:
ci:
name: Run amp.sh
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
name: Checkout Code
- name: Run amp.sh
run: |
FILE="/etc/passwd"
[[ -f ./amp.sh ]] && ./amp.sh || echo "./amp.sh file not present"
git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push --set-upstream origin add-ci-workflow
- Pull Request
- Merge
Write the amp.sh
bash script
git checkout main
git checkout -b php-install
- Create a new file
amp.sh
- We need a shebang to tell the script to use bash
- Helper function to test if a command is available (using this StackOverflow answer with 3323 votes)
- PHP function to install PHP if not available
- We start with PHP because we believe it to be installed already
#!/bin/bash
# Helper functions
checkIsCommandAvailable() {
local commandToCheck="$1"
if command -v "${commandToCheck}" &> /dev/null
then
echo "${commandToCheck} command available"
else
# propagate error to caller
return $?
fi
}
phpInstall() {
if ! checkIsCommandAvailable php
then
echo "PHP is not yet available. Starting installation of PHP"
apt -qy install php
fi
}
phpInstall
git add amp.sh
git update-index --chmod +x ./amp.sh
git commit -m "Add helper function and install PHP"
git push --set-upstream origin php-install
- Pull Request
- Merge