Tools
Tools: AltSchool Of Engineering Tinyuka’24 Month 12 Week 3
2026-02-08
0 views
admin
Automated Web Server Setup with Security Hardening ## Project Overview ## What You Will Learn ## Project Architecture ## Prerequisites ## Project Structure (Industry Standard) ## Step 1: Inventory (Cloud-Ready) ## Step 2: Variables (group_vars) ## Step 3: Main Playbook ## Step 4: Role Tasks ## Step 5: Handlers (Automatic Restarts) ## Step 6: Jinja2 Template (Dynamic Website) ## Step 7: Enable HTTPS (Certbot) ## Step 8: Run the Project ## Final Outcome ## AWS EC2 Compatibility (Important) ## Why This Project Is Portfolio-Worthy ## Next Possible Upgrades (Optional) If you missed our previous session, you can always catch up here. This week, we are going hands on with Automated Web Server Setup with Security Hardening. Let’s get to it, shall we? In this project, you will use Ansible to automatically: Provision and configure multiple web servers Use roles for clean project structure Install and configure Nginx Deploy a dynamic HTML page using Jinja2 Secure the server with UFW Enable HTTPS (TLS/SSL) using Certbot Restart services automatically using handlers Make the setup cloud-ready (AWS EC2 compatible) This mirrors how DevOps teams actually automate servers in production. By completing this project, you will understand: Ansible inventory management Modules (apt, user, copy, service, ufw) Basic security automation Running Ansible against multiple hosts HTTPS with Certbot (Let’s Encrypt) Cloud-ready structure (AWS EC2 compatible) 1 Ansible control node (Linux) 2 Linux servers (Ubuntu recommended) SSH access between control node and servers Basic Linux knowledge Create group_vars/webservers.yml: Clean. Simple. Scalable. roles/webserver/tasks/main.yml roles/webserver/handlers/main.yml Handlers only run when changes occur → efficient & safe. roles/webserver/templates/index.html.j2 Each server now shows its own hostname (proof of automation). Add to tasks/main.yml (after Nginx setup): Enables HTTPS automatically Matches production setups ⚠️ Requires a real domain pointing to the server IP. ansible-playbook -i inventory playbook.yml ✔ Web servers configured consistently
✔ Nginx installed and secured
✔ Firewall enabled
✔ HTTPS enabled
✔ Dynamic content deployed
✔ Fully automated
✔ Cloud-ready You now have a real DevOps-grade automation project. This project works unchanged on AWS EC2 if: Instances allow ports 80 & 443 Security groups are configured SSH key is set in inventory This makes it perfect for: Configuration management Infrastructure as Code principles Many junior DevOps roles expect exactly this level. If you want to go even further later: Integrate Terraform + Ansible Add monitoring with CloudWatch/Prometheus Add Load Balancer (ALB/Nginx) I encourage you to dive deeper into the concepts we've discussed and continue practicing to refine your skills. If you have read all the way to this point thank you So much! I appreciate the effort. If you also found this interesting and would love to take the next steps in the application process do use my referral link below; Apply here or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount! Special Offer: By signing up through the link and using the code shared, you’ll receive a 10% discount! Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program. I would love to hear your feedback and insights. Please leave a comment below to join the conversation! I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the DevOps & Cloud Job Placement / Mentorship Program. For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security. Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers. This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.
Do refer below for the link with a dedicated discount automatically applied at checkout; DevOps & Cloud Job Placement / Mentorship Program. I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey from a beginner’s perspective, aiming to inspire others along the way. If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey. Let’s connect on social media. I’d love to engage and exchange ideas with you! LinkedIn Facebook X Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK:
Control Node (Ansible) | |--- SSH |
-------------------------
| | | |
Web1 Web2 (Optional) Web3 Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
Control Node (Ansible) | |--- SSH |
-------------------------
| | | |
Web1 Web2 (Optional) Web3 CODE_BLOCK:
Control Node (Ansible) | |--- SSH |
-------------------------
| | | |
Web1 Web2 (Optional) Web3 CODE_BLOCK:
ansible-web-project/
├── inventory
├── playbook.yml
├── group_vars/
│ └── webservers.yml
└── roles/ └── webserver/ ├── tasks/ │ └── main.yml ├── handlers/ │ └── main.yml ├── templates/ │ └── index.html.j2 └── files/ Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
ansible-web-project/
├── inventory
├── playbook.yml
├── group_vars/
│ └── webservers.yml
└── roles/ └── webserver/ ├── tasks/ │ └── main.yml ├── handlers/ │ └── main.yml ├── templates/ │ └── index.html.j2 └── files/ CODE_BLOCK:
ansible-web-project/
├── inventory
├── playbook.yml
├── group_vars/
│ └── webservers.yml
└── roles/ └── webserver/ ├── tasks/ │ └── main.yml ├── handlers/ │ └── main.yml ├── templates/ │ └── index.html.j2 └── files/ CODE_BLOCK:
[webservers]
web1 ansible_host=18.210.12.10
web2 ansible_host=3.92.55.23 [all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/aws-key.pem Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
[webservers]
web1 ansible_host=18.210.12.10
web2 ansible_host=3.92.55.23 [all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/aws-key.pem CODE_BLOCK:
[webservers]
web1 ansible_host=18.210.12.10
web2 ansible_host=3.92.55.23 [all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/aws-key.pem CODE_BLOCK:
app_user: appuser
http_port: 80
domain_name: example.com
email: [email protected]
Variables make the project flexible and reusable. Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
app_user: appuser
http_port: 80
domain_name: example.com
email: [email protected]
Variables make the project flexible and reusable. CODE_BLOCK:
app_user: appuser
http_port: 80
domain_name: example.com
email: [email protected]
Variables make the project flexible and reusable. CODE_BLOCK:
- name: Configure Production Web Servers hosts: webservers become: yes roles: - webserver Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
- name: Configure Production Web Servers hosts: webservers become: yes roles: - webserver CODE_BLOCK:
- name: Configure Production Web Servers hosts: webservers become: yes roles: - webserver CODE_BLOCK:
- name: Update system packages apt: update_cache: yes - name: Install required packages apt: name: - nginx - ufw - certbot - python3-certbot-nginx state: present - name: Create application user user: name: "{{ app_user }}" shell: /bin/bash - name: Allow HTTP and HTTPS ufw: rule: allow port: "{{ item }}" loop: - "80" - "443" - name: Enable firewall ufw: state: enabled - name: Deploy website template template: src: index.html.j2 dest: /var/www/html/index.html notify: Restart Nginx - name: Ensure Nginx is running service: name: nginx state: started enabled: yes Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
- name: Update system packages apt: update_cache: yes - name: Install required packages apt: name: - nginx - ufw - certbot - python3-certbot-nginx state: present - name: Create application user user: name: "{{ app_user }}" shell: /bin/bash - name: Allow HTTP and HTTPS ufw: rule: allow port: "{{ item }}" loop: - "80" - "443" - name: Enable firewall ufw: state: enabled - name: Deploy website template template: src: index.html.j2 dest: /var/www/html/index.html notify: Restart Nginx - name: Ensure Nginx is running service: name: nginx state: started enabled: yes CODE_BLOCK:
- name: Update system packages apt: update_cache: yes - name: Install required packages apt: name: - nginx - ufw - certbot - python3-certbot-nginx state: present - name: Create application user user: name: "{{ app_user }}" shell: /bin/bash - name: Allow HTTP and HTTPS ufw: rule: allow port: "{{ item }}" loop: - "80" - "443" - name: Enable firewall ufw: state: enabled - name: Deploy website template template: src: index.html.j2 dest: /var/www/html/index.html notify: Restart Nginx - name: Ensure Nginx is running service: name: nginx state: started enabled: yes CODE_BLOCK:
- name: Restart Nginx service: name: nginx state: restarted Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
- name: Restart Nginx service: name: nginx state: restarted CODE_BLOCK:
- name: Restart Nginx service: name: nginx state: restarted CODE_BLOCK:
<!DOCTYPE html>
<html>
<head> <title>{{ inventory_hostname }}</title>
</head>
<body> <h1>🚀 Deployed with Ansible</h1> <p>Server: {{ inventory_hostname }}</p> <p>Managed by Ansible automation</p>
</body>
</html> Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
<!DOCTYPE html>
<html>
<head> <title>{{ inventory_hostname }}</title>
</head>
<body> <h1>🚀 Deployed with Ansible</h1> <p>Server: {{ inventory_hostname }}</p> <p>Managed by Ansible automation</p>
</body>
</html> CODE_BLOCK:
<!DOCTYPE html>
<html>
<head> <title>{{ inventory_hostname }}</title>
</head>
<body> <h1>🚀 Deployed with Ansible</h1> <p>Server: {{ inventory_hostname }}</p> <p>Managed by Ansible automation</p>
</body>
</html> CODE_BLOCK:
- name: Obtain SSL certificate command: > certbot --nginx -d {{ domain_name }} --non-interactive --agree-tos -m {{ email }} notify: Restart Nginx Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
- name: Obtain SSL certificate command: > certbot --nginx -d {{ domain_name }} --non-interactive --agree-tos -m {{ email }} notify: Restart Nginx CODE_BLOCK:
- name: Obtain SSL certificate command: > certbot --nginx -d {{ domain_name }} --non-interactive --agree-tos -m {{ email }} notify: Restart Nginx - Provision and configure multiple web servers
- Use roles for clean project structure
- Install and configure Nginx
- Deploy a dynamic HTML page using Jinja2
- Secure the server with UFW
- Enable HTTPS (TLS/SSL) using Certbot
- Restart services automatically using handlers
- Make the setup cloud-ready (AWS EC2 compatible) - Ansible inventory management
- Playbooks and tasks
- Modules (apt, user, copy, service, ufw)
- Idempotency
- Basic security automation
- Running Ansible against multiple hosts - Ansible Roles
- Jinja2 Templates
- HTTPS with Certbot (Let’s Encrypt)
- Cloud-ready structure (AWS EC2 compatible) - 1 Ansible control node (Linux)
- 2 Linux servers (Ubuntu recommended)
- SSH access between control node and servers
- Basic Linux knowledge - Works locally
- Works on AWS EC2
- No changes needed later - Secures your site
- Enables HTTPS automatically
- Matches production setups - Instances allow ports 80 & 443
- Security groups are configured
- SSH key is set in inventory - Portfolio projects
- Interview demos - Configuration management
- Security automation
- Infrastructure as Code principles
- Production thinking
- Clean Ansible design - Integrate Terraform + Ansible
- Add monitoring with CloudWatch/Prometheus
- Add CI/CD pipeline
- Add Ansible Vault
- Add Load Balancer (ALB/Nginx)
how-totutorialguidedev.toaimllinuxubuntuserverbashshellfirewallnginxnodepython