Building and Securing a Mini Production-Ready Web Infrastructure
(Without Coding a Backend)
This technical report documents the successful implementation of a production-ready web infrastructure system. Our team has deployed, configured, and secured a complete web server environment demonstrating modern DevOps practices including remote access, web server configuration, API interaction, load balancing, SSL/TLS encryption, firewall management, and system debugging.
As part of the IT Operations and Infrastructure team for a small company preparing to launch an online platform, our objective was to prepare, secure, test, and validate the infrastructure before application deployment. This assignment focuses on demonstrating how modern web systems are deployed, secured, accessed, monitored, and debugged using real tools, protocols, and configurations.
Demonstrate modern web system deployment practices using industry-standard tools and protocols.
Implement comprehensive security best practices including SSL/TLS encryption and firewall configuration.
Configure and test load balancing mechanisms for high availability and performance optimization.
Monitor, debug, and troubleshoot common infrastructure issues with systematic approaches.
| Component | Technology | Version |
|---|---|---|
| Operating System | Ubuntu (WSL2) | 24.04.3 LTS |
| Web Server | Nginx | Latest |
| Load Balancer | HAProxy | Latest |
| SSL/TLS | Let's Encrypt (Certbot) | Latest |
| Firewall | UFW | 0.36.2-6 |
| Remote Access | OpenSSH | 1:9.6p1-3ubuntu13.14 |
| API Testing | Postman | Latest |
Demonstrate secure remote server access using SSH with both password-based and key-based authentication methods, including file transfer capabilities.
Installed OpenSSH server on Ubuntu WSL2 environment.
sudo apt update
sudo apt install openssh-server -y
sudo service ssh start
OpenSSH server installation showing package list reading, dependency tree building, and successful installation confirmation. System information displayed after first SSH login with password authentication.
Verified basic SSH connectivity using password authentication.
ssh winebald@localhost
Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.6.87.2-microsoft-standard-WSL2 x86_64)
Generated ED25519 SSH key pair for enhanced security.
ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/winebald/.ssh/id_ed25519): /home/winebald/.ssh/id_rsa
Your identification has been saved in /home/winebald/.ssh/id_rsa
Your public key has been saved in /home/winebald/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:cUX24fRz0wRz0pkb5FYeWZugTJ8pTiI winebald@WINEBALD
ED25519 SSH key pair generation displaying public/private key creation, fingerprint (SHA256:cUX24fRz0wRz0pkb5FYeWZugTJ8pTiI), and randomart image for visual key verification.
Configured authorized_keys for passwordless authentication.
sudo cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
sudo cat << 'EOF' >> /etc/ssh/ssh_config
Host *
PasswordAuthentication no
IdentityFile ~/.ssh/id_rsa
EOF
ssh -i ~/.ssh/id_rsa winebald@localhost
Last login: Tue Jan 20 11:55:21 2026 from 127.0.0.1
Passwordless SSH authentication using private key (-i ~/.ssh/id_rsa). System welcome message shows Ubuntu 24.04.3 LTS with last login timestamp from 127.0.0.1, demonstrating successful key-based access.
Demonstrated file transfer using SCP protocol.
scp /var/www/html/index.html winebald@localhost:/mnt/c/Users/USER/Downloads
winebald@localhost's password:
index.html 100% 20 12.6KB/s 00:00
SCP (Secure Copy Protocol) demonstration transferring index.html file from /var/www/html to remote destination. Transfer completed at 12.6KB/s showing 100% completion for 20-byte file.
| Method | Security Level | Use Case | Status |
|---|---|---|---|
| Password Authentication | Moderate | Quick access, testing | Verified |
| Key-Based Authentication | High | Production, automation | Verified |
| SCP File Transfer | High | Secure file operations | Verified |
Install and configure Nginx web server to handle HTTP requests, demonstrate various HTTP methods, status codes, and headers without backend development.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /api/read {
limit_except GET {
deny all;
}
return 200 '{"status": "200 OK"}';
}
location /api/submit {
limit_except POST {
deny all;
}
return 201 '{"status": "201 Created"}';
}
location /api/update {
limit_except PUT {
deny all;
}
return 200 '{"status": "200 OK"}';
}
location /api/delete {
limit_except DELETE {
deny all;
}
return 204 '{"status": "204 No Content"}';
}
location /redirect {
return 301 https://github.com/banituze;
}
}
curl -X GET localhost/api/read
{"status": "200 OK"}
curl -X POST localhost/api/submit
{"status": "201 Created"}
curl -X PUT localhost/api/update
{"status": "200 OK"}
curl -X DELETE localhost/api/delete
{"status": "204 No Content"}
curl -H "Content-Type: application/json" localhost
Hello from Group D!
cURL commands demonstrating all HTTP methods (GET, POST, PUT, DELETE) with their respective status codes and JSON responses. Custom header example shows Content-Type: application/json with server response 'Hello from Group D!'
| Status Code | Description | Endpoint | Verification |
|---|---|---|---|
| 200 OK | Request succeeded | /api/read, /api/update | Verified |
| 201 Created | Resource created | /api/submit | Verified |
| 204 No Content | Success, no content | /api/delete | Verified |
| 301 Moved Permanently | Permanent redirect | /redirect | Verified |
| 403 Forbidden | Access denied | Wrong HTTP method | Verified |
| 404 Not Found | Resource not found | Non-existent paths | Verified |
Demonstrate complete CRUD operations using the OpenAI API with proper authentication, error handling, and response validation using Postman.
OpenAI API
Base URL: https://api.openai.com/v1
Bearer Token
API Key stored in Postman environment variables
Postman Runner interface showing successful execution of OpenAI CRUD collection. Results display all four operations (Create, Read, Update, Delete Conversation) with PASS status. Test assertions verified including "Status code is 200", "Saved conversation_id to environment", "Conversation deleted successfully", and "conversation_id removed from environment". Performance metrics show response times ranging from 635ms to 1271ms with 100% test success rate. Environment variables properly managed for conversation ID persistence across requests.
| Operation | Endpoint | Method | Status Code | Response Time | Result |
|---|---|---|---|---|---|
| Create Conversation | /conversations | POST | 200 OK | 1271ms | PASS |
| Read Conversation | /conversations/id | GET | 200 OK | 783ms | PASS |
| Update Conversation | /conversations/id/items | POST | 200 OK | 803ms | PASS |
| Delete Conversation | /conversations/id | DELETE | 200 OK | 635ms | PASS |
Implement HAProxy load balancer to distribute traffic between multiple backend servers, demonstrating round-robin algorithm and failover capabilities.
frontend lb-frontend
bind *:80
redirect scheme https code 301 if !{ ssl_fc }
bind *:443 ssl crt /etc/letsencrypt/live/web.banituze.tech/banituze.pem
default_backend lb-backend
backend lb-backend
balance roundrobin
server web01 3.86.59.154:80 check
server web02 54.227.118.239:80 check
HAProxy configuration showing combined PEM certificate creation, frontend/backend setup with SSL termination, round-robin load balancing between two servers (3.86.59.154:80 and 54.227.118.239:80), and service restart/reload commands.
Distributes requests evenly across all available backend servers in sequential order.
Status: Active
Automatic server health monitoring with check keyword ensuring only healthy servers receive traffic.
Status: Enabled
| Server Name | IP Address | Port | Health Check | Status |
|---|---|---|---|---|
| web01 | 3.86.59.154 | 80 | Enabled | UP |
| web02 | 54.227.118.239 | 80 | Enabled | UP |
for i in {1..10}; do curl web.banituze.tech; done
Result: Traffic distributed evenly between both servers
- Request 1, 3, 5, 7, 9: web01 (3.86.59.154)
- Request 2, 4, 6, 8, 10: web02 (54.227.118.239)
Verification: Round-robin distribution confirmed
Failover: Automatic rerouting when one server is down
Load balancer configured with SSL termination, handling HTTPS traffic and redirecting HTTP to HTTPS automatically.
Security Feature: Automatic HTTP to HTTPS redirect with 301 status code
Certificate: Let's Encrypt SSL certificate integrated at load balancer level
Implement SSL/TLS encryption using Let's Encrypt certificates to secure web traffic and establish HTTPS connectivity.
sudo apt install certbot -y
sudo certbot certonly --manual --preferred-challenges dns -d web.banituze.tech
Please deploy a DNS TXT record under the name:
_acme-challenge.web.banituze.tech
with the following value:
cQxFzUFbk9ArUiLMRS0hZqgH6QhuQfnLUvPtnwm7mBg
Certbot manual DNS challenge for web.banituze.tech domain showing TXT record requirement (_acme-challenge.web.banituze.tech) with validation value. Successfully received certificate saved at /etc/letsencrypt/live/web.banituze.tech/ with expiration date 2026-04-20.
DNS TXT record deployed and verified through Admin Toolbox.
Verification successful - Certificate issued
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/web.banituze.tech/fullchain.pem
Key is saved at: /etc/letsencrypt/live/web.banituze.tech/privkey.pem
This certificate expires on 2026-04-20.
sudo bash -c "cat /etc/letsencrypt/live/web.banituze.tech/fullchain.pem /etc/letsencrypt/live/web.banituze.tech/privkey.pem > /etc/letsencrypt/live/web.banituze.tech/banituze.pem"
sudo service haproxy restart
sudo service haproxy reload
| Parameter | Value |
|---|---|
| Domain | web.banituze.tech |
| Certificate Authority | Let's Encrypt |
| Validation Method | DNS Challenge (TXT Record) |
| Certificate Type | Domain Validated (DV) |
| Validity Period | 90 days |
| Expiration Date | April 20, 2026 |
| Renewal | Manual (--manual flag used) |
All data transmitted between client and server is encrypted using TLS 1.2/1.3 protocols.
Valid SSL certificate eliminates browser security warnings and displays padlock icon.
HTTPS is a ranking factor for search engines, improving website visibility.
Meets security standards required for handling sensitive data and financial transactions.
Configure UFW (Uncomplicated Firewall) to control network access, implementing security policies for SSH, HTTP, and HTTPS services.
sudo apt update -y
sudo apt install ufw -y
sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
UFW (Uncomplicated Firewall) installation process showing apt update, package installation with dependencies (libip4tc2, libip6tc2, libnetfilter-conntrack3, iptables), and ufw enable command with SSH connection warning prompt.
sudo ufw allow 22/tcp
Rule added
Rule added (v6)
sudo ufw allow 443/tcp
Rule added
Rule added (v6)
sudo ufw allow 80/tcp
Rule added
Rule added (v6)
Complete UFW firewall rule implementation showing configuration file creation, package setup, trigger processing, and systemd service enablement. All rules added for ports 22/tcp, 443/tcp, and 80/tcp with IPv4 and IPv6 support.
| Port | Protocol | Service | Action | Source |
|---|---|---|---|---|
| 22 | TCP | SSH | ALLOW IN | Anywhere |
| 80 | TCP | HTTP | ALLOW IN | Anywhere |
| 443 | TCP | HTTPS | ALLOW IN | Anywhere |
| 8080 | TCP | Alternative HTTP | DENY IN | Anywhere |
Incoming: Deny all by default
Outgoing: Allow all by default
Status: Active
SSH (22) - Remote administration
HTTP (80) - Web traffic
HTTPS (443) - Secure web traffic
sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
8080/tcp DENY IN Anywhere
Identify, diagnose, and resolve common web server issues using systematic troubleshooting techniques.
Problem: Server fails to start due to port already in use
Diagnosis:
sudo ss -tulpn | grep :80
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=10566,fd=5)
Solution:
sudo kill 10566
sudo service nginx start
Resolution: Service started successfully after killing conflicting process
Problem: Access denied due to incorrect file permissions
Diagnosis:
ls -la /var/www/html/
drwx------ 2 root root 4096 Jan 20 12:00 .
Solution:
sudo chmod -R 755 /var/www/html
sudo chown -R www-data:www-data /var/www/html
Resolution: Proper permissions restored, content now accessible
Problem: Incorrect firewall rules blocking legitimate traffic
Diagnosis:
sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
Solution:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
Resolution: Required ports opened, traffic now flowing correctly
sudo cat /var/log/nginx/access.log
sudo nginx -t
curl -v localhost
sudo service nginx status
Location: /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /api/read {
limit_except GET { deny all; }
return 200 '{"status": "200 OK"}';
}
location /api/submit {
limit_except POST { deny all; }
return 201 '{"status": "201 Created"}';
}
location /api/update {
limit_except PUT { deny all; }
return 200 '{"status": "200 OK"}';
}
location /api/delete {
limit_except DELETE { deny all; }
return 204 '{"status": "204 No Content"}';
}
location /redirect {
return 301 https://github.com/banituze;
}
}
Location: /etc/haproxy/haproxy.cfg
frontend lb-frontend
bind *:80
redirect scheme https code 301 if !{ ssl_fc }
bind *:443 ssl crt /etc/letsencrypt/live/web.banituze.tech/banituze.pem
default_backend lb-backend
backend lb-backend
balance roundrobin
server web01 3.86.59.154:80 check
server web02 54.227.118.239:80 check
sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 443/tcp ALLOW IN Anywhere
[ 3] 80/tcp ALLOW IN Anywhere
SSH key-based authentication provides superior security compared to password authentication by eliminating brute force vulnerabilities and enabling secure automation.
Load balancing significantly improves system availability and performance by distributing traffic across multiple servers and providing automatic failover capabilities.
SSL/TLS encryption is essential for modern web services, protecting data in transit and establishing trust with users through browser security indicators.
Proper firewall configuration following the principle of least privilege prevents unauthorized access while maintaining necessary service availability.
Understanding HTTP methods, status codes, and headers is crucial for building RESTful APIs and debugging web applications effectively.
Methodical troubleshooting using log analysis, configuration testing, and network diagnostics is essential for rapid problem resolution.
Challenge: Multiple services attempting to bind to the same ports causing startup failures.
Resolution: Used ss to identify conflicting processes and implemented proper service shutdown procedures before starting new services.
Challenge: Manual DNS challenge required external DNS provider configuration and verification timing.
Resolution: Properly configured DNS TXT records and waited for propagation before completing certificate acquisition.
Challenge: HAProxy SSL termination required combining fullchain and private key into single PEM file.
Resolution: Created combined certificate file and updated HAProxy configuration with proper SSL binding directives.
Challenge: Initial firewall configuration too restrictive, blocking necessary web traffic.
Resolution: Systematically opened required ports (22, 80, 443) while maintaining security posture.
Implement Certbot auto-renewal hooks to prevent certificate expiration and eliminate manual intervention.
Deploy comprehensive monitoring solution (Prometheus/Grafana) with alerting for service downtime and performance degradation.
Migrate infrastructure to Docker containers for improved portability, scalability, and consistency across environments.
Implement automated deployment pipeline using GitHub Actions or GitLab CI for continuous integration and delivery.
This project successfully demonstrated the implementation of a complete production-ready web infrastructure without backend development. We accomplished all seven required tasks, implementing SSH authentication, web server configuration, API interaction, load balancing, SSL/TLS encryption, firewall security, and systematic debugging.
The infrastructure deployed meets industry standards for security, availability, and performance. Through hands-on implementation, our team gained practical experience with essential DevOps tools and practices including Nginx web server, HAProxy load balancer, Let's Encrypt SSL certificates, UFW firewall, OpenSSH server, and Postman API testing.
ALL SYSTEMS OPERATIONAL
INFRASTRUCTURE DEPLOYMENT: COMPLETE
SECURITY STATUS: VERIFIED
PROJECT STATUS: SUCCESS
The knowledge and skills acquired through this project provide a solid foundation for managing production infrastructure in real-world scenarios. Our team is prepared to demonstrate the live system and explain the technical implementation decisions made throughout the deployment process.