Objective. Students will write a fully documented Bash provisioning script that configures a fresh Ubuntu VM as a ready-to-use web development server, incorporating skills from all prior lessons.
This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.
VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.
This lab is your opportunity to bring together every skill you have practiced in this course — user management, package installation, firewall configuration, Apache setup, SSH hardening, cron jobs, and service management — into a single, professional Bash script called `provision.sh`. When it finishes running on a clean Ubuntu virtual machine, that machine should be a fully functional web development server without any additional manual steps.
In professional environments, servers are rarely configured by hand. A provisioning script lets a team spin up identical environments in minutes, reduces human error, and documents every decision in executable form. Tools such as Ansible and Terraform do this at scale, but hand-written Bash provisioning scripts remain the foundation of the discipline and are directly testable by interviewers.
Every production-quality Bash script begins with a strict error-handling declaration:
```bash
#!/usr/bin/env bash
set -euo pipefail
```
These three flags together form a widely accepted safety baseline. Without them, a failed `apt-get install` command could be silently ignored and the rest of the script could run on a broken system.
Every significant action should be recorded to a log file so you can audit what happened after the fact. A simple pattern is:
```bash
LOGFILE="/var/log/provision.log"
exec > >(tee -a "$LOGFILE") 2>&1
```
This redirects both standard output and standard error to the terminal and to the log file simultaneously. Date-stamped log entries help with troubleshooting.
Before writing a single line of code, you must produce a written specification. A good spec answers: What user accounts are needed and what groups do they belong to? Which packages must be installed? What firewall ports must be open and why? What Apache virtual host configuration is required? Which SSH settings must be changed from their defaults? What cron job must run, on what schedule, doing what? Which services must be enabled and started?
Having the instructor review your spec before you code catches design problems early and mirrors real workplace practice where a tech lead reviews infrastructure plans before implementation.
Build your script in sections and test each section on a clean VM snapshot before moving to the next. Snapshots let you roll back to a known-good state instantly. A typical build order follows the logical dependency chain: update package lists, create users, install packages, configure firewall, configure Apache, harden SSH, add cron job, enable and start services, print a completion message.
Test each section by running only that portion of the script, verifying the result manually, then taking a new snapshot. Never test destructive operations on a machine that holds data you cannot afford to lose.
User creation: Use `useradd` or `adduser` with appropriate flags. Lock the password of service accounts. Add users to the correct groups (`sudo`, `www-data`).
Package installation: Use `apt-get install -y` so the script does not pause waiting for user confirmation. Always run `apt-get update` immediately before installing packages to avoid stale cache errors.
Firewall rules: Use `ufw` (Uncomplicated Firewall). Enable it with `ufw --force enable` so the script does not hang waiting for interactive confirmation. Open only the ports your server actually needs — typically 22 (SSH), 80 (HTTP), and 443 (HTTPS). Deny all other inbound traffic by default.
Apache configuration: Place virtual host configuration files in `/etc/apache2/sites-available/`, enable them with `a2ensite`, and disable the default site if it is not needed. Enable required Apache modules with `a2enmod`.
SSH hardening: Edit `/etc/ssh/sshd_config` to disable root login (`PermitRootLogin no`) and optionally disable password authentication in favor of key-based authentication. Use `sed` or a here-doc to make these changes programmatically. Reload or restart `sshd` after any configuration change.
Cron job: Add entries to `/etc/cron.d/` or use `crontab` non-interactively. Document the schedule in an inline comment.
Service enablement: Use `systemctl enable` and `systemctl start` for Apache and SSH. Check that services are active with `systemctl is-active` and exit with an error if they are not.
Every non-obvious line of your script must have an inline comment explaining why, not just what. Your one-page README must describe: the purpose of the script, how to run it, what the script configures, any prerequisites, and known limitations. This documentation is evaluated separately from the script itself.
During your demo, you will run `provision.sh` on a clean Ubuntu VM while narrating each section. The instructor will ask two questions about your design decisions — for example, why you chose a particular firewall rule or how you handled a potential error. Prepare by re-reading your spec and being able to explain every line.
The instructor will run your submitted script on a clean VM using the published rubric. The script must exit with status 0, meaning no errors. All required configurations must be present and functional. The README must explain all major sections. A score of 85% or higher on rubric points is required to pass. Review the rubric before you begin so you know exactly what is being evaluated.
Answer each question, then check it. Nothing is recorded; this is your own practice.
A free tech program — complimentary, as our commitment to get America working. Help us build VoTechWorks. Tell us what works, what doesn’t, and what you want to learn.