A bash script that installs Docker CE, generates a self-signed TLS certificate chain, and launches an NGINX reverse-proxy container in front of an Apache2 container using Docker Compose. NGINX terminates HTTPS and forwards plaintext HTTP traffic to Apache. All configurable parameters (host IP, hostname, port, image names, log directory) are read from a single config file.
- Reads all runtime parameters from
./configin the same directory as the script - Creates directories
certs/,etc/, and$NGINX_LOG_DIRif they do not exist - Installs Docker CE from the official Docker apt repository
- Installs docker-compose v1.21.2 from the official GitHub release binary
- Generates a root CA key and self-signed certificate (
certs/root.key,certs/root.crt) - Generates an NGINX server certificate signed by the root CA (
certs/web.key,certs/web.crt) with SubjectAltNames containing the Docker host's IP address and hostname fromconfig - Appends the root CA to
certs/web.crtto form a complete certificate chain - Writes
etc/nginx.conf— an SSL server block that proxies all requests to theapachecontainer - Writes
docker-compose.yml— launchesnginx:1.13andhttpd:2.4on a shared default network; mounts the config, certificates, and log directory into the nginx container - Brings both containers up with
docker-compose up -d
The config file is sourced by the script and defines all tuneable parameters:
# Host parameters
EXTERNAL_IP=10.157.1.14
HOST_NAME=docker-vm.dlnet.kharkov.com
# Docker parameters
NGINX_IMAGE="nginx:1.13"
APACHE_IMAGE="httpd:2.4"
NGINX_PORT=445
NGINX_LOG_DIR=/srv/log/nginx| Parameter | Description |
|---|---|
EXTERNAL_IP |
IP address of the Docker host; added to the certificate SAN and /etc/hosts |
HOST_NAME |
FQDN of the Docker host; added to the certificate SAN and /etc/hosts |
NGINX_IMAGE |
Docker image for the NGINX container (must be nginx:1.13) |
APACHE_IMAGE |
Docker image for the Apache container (must be httpd:2.4) |
NGINX_PORT |
Host port that NGINX listens on for HTTPS traffic |
NGINX_LOG_DIR |
Absolute path on the host where NGINX access/error logs are written |
After task10_12_2.sh completes successfully the following layout must be present in the repository directory:
WORKDIR
├── certs
│ ├── root.crt # root CA certificate (used to verify the HTTPS connection)
│ ├── web.crt # NGINX certificate (chain: server cert + root CA)
│ └── web.key # NGINX private key
├── config # parameters file
├── docker-compose.yml # generated by the script
├── etc
│ └── nginx.conf # generated by the script
└── task10_12_2.sh # entry point
The grader runs the script on a freshly installed Ubuntu 16.04 (Xenial) VM as root with internet access. Replicate this environment locally to test before submission.
Prerequisites: VirtualBox and Vagrant installed.
Create a Vagrantfile in any working directory:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.network "forwarded_port", guest: 445, host: 445
config.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
end# Start the VM and open a root shell
vagrant up
vagrant ssh
sudo -i
# Clone the repository
git clone https://github.com/<your-username>/task10_12_2 /root/task10_12_2
cd /root/task10_12_2
# Set HOST_NAME and EXTERNAL_IP in config to match the VM's address, then run:
bash task10_12_2.shTo verify from the host machine (after port forwarding is set up):
# Copy certs/root.crt out of the VM first:
vagrant scp default:/root/task10_12_2/certs/root.crt ./root.crt
curl --cacert root.crt --resolve docker-vm.dlnet.kharkov.com:445:127.0.0.1 \
https://docker-vm.dlnet.kharkov.com:445To re-use the VM later:
vagrant halt
vagrant up
vagrant sshTo start fresh:
vagrant destroy -f
vagrant upPrerequisites: Multipass installed.
# Launch a Ubuntu 16.04 instance
multipass launch xenial --name nginx-test --mem 1G
# Open a shell
multipass shell nginx-testInside the instance:
sudo -i
apt-get install -y git
git clone https://github.com/<your-username>/task10_12_2 /root/task10_12_2
cd /root/task10_12_2
bash task10_12_2.shRun these commands inside the VM/instance after task10_12_2.sh completes:
# 1. Confirm both containers are running
docker-compose ps
# 2. Send a test HTTPS request using the generated root CA
source ./config
curl --cacert certs/root.crt https://${HOST_NAME}:${NGINX_PORT}
# Expected: response body contains "It works!"
# 3. Confirm the access log was written to the host
cat ${NGINX_LOG_DIR}/access.log
# 4. Check certificate SAN fields
openssl x509 -in certs/web.crt -text -noout | grep -A4 "Subject Alternative Name"
# Expected: IP:$EXTERNAL_IP and DNS:$HOST_NAME| Check | Command | Expected result |
|---|---|---|
| Both containers running | docker-compose ps |
nginx and apache show Up |
| HTTPS returns Apache page | curl --cacert certs/root.crt https://$HOST_NAME:$NGINX_PORT |
Body contains It works! |
certs/root.crt present |
ls certs/root.crt |
File exists |
certs/web.crt present |
ls certs/web.crt |
File exists |
certs/web.key present |
ls certs/web.key |
File exists |
etc/nginx.conf present |
ls etc/nginx.conf |
File exists |
docker-compose.yml present |
ls docker-compose.yml |
File exists |
NGINX image is nginx:1.13 |
docker inspect <nginx-container> | grep '"Image"' |
nginx:1.13 |
Apache image is httpd:2.4 |
docker inspect <apache-container> | grep '"Image"' |
httpd:2.4 |
| Certificate SAN contains host IP | openssl x509 -in certs/web.crt -text -noout | grep IP |
Shows $EXTERNAL_IP |
| Certificate SAN contains hostname | openssl x509 -in certs/web.crt -text -noout | grep DNS |
Shows $HOST_NAME |
| NGINX logs written to host | cat $NGINX_LOG_DIR/access.log |
Contains at least one log entry |
- OS: Ubuntu Xenial 16.04 Server (
xenial-server-cloudimg-amd64-disk1.img) - User:
root - Network: internet access available
- Pre-installed packages: only what ships with the base image
- The repository is cloned by URL (repository must be named
task10_12_2); a different name causes automatic failure. task10_12_2.shis executed from the repository root; a different script name or subdirectory location causes automatic failure.
- HTTPS connectivity — an HTTPS
GETrequest is made to the Docker host on$NGINX_PORTusingcerts/root.crtas the trusted CA. The response must contain the default Apache2 page (It works!). - Container presence — two containers must be running with base images
nginx:1.13andhttpd:2.4. - Volume mounts — the nginx container must have
etc/nginx.conf, thecerts/directory, and$NGINX_LOG_DIRmounted. - Access log — at least one entry must exist in
$NGINX_LOG_DIR/access.logon the host after the HTTPS request. - File structure —
docker-compose.yml,etc/nginx.conf, and thecerts/directory must all be present in the project directory.
- The completed assignment must be in a separate repository on github.com (e.g.
https://github.com/user/task10_12_2). - A freshly installed VM from
xenial-server-cloudimg-amd64-disk1.imgis used for verification. - Any additional packages beyond those in the image may be installed; installation must be handled by the script.
- Scripts are executed as
root. - The assignment must be submitted by 23:59 on 13/05/18.
