🚧 Under construction — VoTechWorks is being built. A free tech program — complimentary, as our commitment to get America working.
voTechWorksGrade 13 · a vocational technology learning center, by urbanicity
newSchoolWorks.com › VoTechWorks › Technology & Design › Web & Software Development › Linux/Bash for Web & Software Development › Lesson 12
TEC-WEB46-06 · Lesson 12 · 18 clock hours · lab

Capstone Integration Lab: Linux Server Provisioning Script

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.

⚠ Pending professional review

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.

Capstone Integration Lab: Linux Server Provisioning Script

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.

Why Provisioning Scripts Matter

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.

Script Architecture and Safety Defaults

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.

Logging

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.

Project Planning Phase

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.

Incremental Development with Snapshots

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.

Key Sections in Detail

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.

Inline Comments and README

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.

Demo and Defense

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.

Grading and the 85% Threshold

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.

Key terms9

set -euo pipefailA Bash directive that causes the script to exit on any error (-e), treats unset variables as errors (-u), and fails a pipeline if any stage fails (-o pipefail); forms a standard safety baseline for production scripts.
Provisioning scriptAn automated script that configures a fresh server to a desired state — installing packages, creating users, and applying settings — so the process is repeatable and consistent.
VM snapshotA saved point-in-time copy of a virtual machine's disk and state that can be restored instantly, allowing safe testing of script sections without permanent consequences.
ufw (Uncomplicated Firewall)A user-friendly front end for managing iptables firewall rules on Ubuntu and Debian-based systems, used to open or close network ports.
systemctlThe command-line tool for controlling systemd services; used to start, stop, enable, disable, and check the status of services such as Apache and SSH.
teeA Unix utility that reads from standard input and writes to both standard output and one or more files simultaneously, commonly used to log script output while still displaying it on the terminal.
sshd_configThe main configuration file for the OpenSSH server daemon, located at /etc/ssh/sshd_config, where settings such as PermitRootLogin and PasswordAuthentication are defined.
Exit statusA numeric code returned by a command or script when it finishes; 0 indicates success, and any non-zero value indicates an error; used by set -e and by automated grading to confirm a script completed without failure.
a2ensite / a2enmodApache2 utility commands on Debian-based systems that enable a named virtual host configuration (a2ensite) or Apache module (a2enmod), creating the required symbolic links in the Apache configuration tree.
In class: Project planning: students draft a written specification listing the exact tasks their script must perform (user creation, package installation, firewall rules, Apache configuration, SSH hardening, cron job, service enablement) and have it reviewed by the instructor before coding. · Script development: students build 'provision.sh' incrementally across multiple work sessions, testing each section on a clean VM snapshot; they use set -euo pipefail, inline comments, and a log file; instructor circulates and provides formative feedback. · Demo and defense: each student runs provision.sh on a fresh VM in front of the class, narrates what each section does, answers two instructor questions about design decisions, and submits the final script with a one-page README.
Materials: Student VMs, all prior lesson materials, provision.sh rubric, README template
Check: Instructor runs provision.sh on a clean VM using the grading rubric; all required configurations must be present and functional, script must exit 0, README must explain all major sections — pass requires 85% of rubric points.

Practice check8

Answer each question, then check it. Nothing is recorded; this is your own practice.

Scripting, Programming, and Software Development
1. A student's provision.sh script fails silently when an apt-get install command returns a non-zero exit code and continues running subsequent sections. Which addition to the script would have prevented this behavior?
Security
2. Which command enables the UFW firewall non-interactively inside a provisioning script, preventing the script from pausing to wait for user confirmation?
Scripting, Programming, and Software Development
3. A student wants to redirect both standard output and standard error from their provision.sh script to a log file while still displaying output on the terminal. Which line accomplishes this?
Security
4. After editing /etc/ssh/sshd_config to set PermitRootLogin no, what must the script do to apply the change?
Scripting, Programming, and Software Development
5. Which sequence of commands correctly installs a package non-interactively and avoids stale cache errors in a provisioning script?
Scripting, Programming, and Software Development
6. A student's script exits with status code 1 after the instructor runs it during grading. What does this indicate according to Linux conventions?
Scripting, Programming, and Software Development
7. Why should a student test each section of provision.sh on a clean VM snapshot rather than continuing on the same running VM after each test?
Scripting, Programming, and Software Development
8. Which Apache command enables a virtual host configuration file named mysite.conf so that Apache will serve it?
Record this lesson on my transcript. Sign in with your key and enrollment email to record lessons (enroll free if you have no key). This page stays open to read and practise.