← Back to All Projects

Web Server

October 2025 Forever Project

Making and maintaining my very own Web Server. The very one you are looking at right now! All hosted and maintained locally and independently.

  • HTML
  • CSS
  • PHP
  • SQL
  • JavaScript
  • Apache
  • MySQL
  • PHPMyAdmin
  • Cloudflare
  • DNS
  • Automation
Web Server Screenshot

Project Overview

This portfolio website represents my comprehensive full-stack web development capabilities, built from the ground up using the LAMP stack (Linux/Apache, MySQL, PHP). I designed this project to be more than just a simple portfolio—it's a production-grade content management system with advanced features like GitHub API integration, traffic analytics, and a robust admin panel.

What started as a school assignment evolved into a professional platform that showcases not only my projects but also my understanding of secure web development, database architecture, and modern web design principles. Every line of code was written by me, from the dual-database security model to the responsive CSS framework.

My Role

Solo Entrepreneur

Sole Developer, Designer and Maintainer

What Made This Project Successful

The strength of this project lies in its security-first architecture and professional design standards. I implemented a dual-user database separation model where public pages use a read-only MySQL user while admin operations require authentication AND a separate write-capable user. This defense-in-depth approach means that even if someone exploits a SQL injection vulnerability on the public site, they can only read data—never modify or delete it.

The admin panel is fully featured with RBAC (role-based access control), session management with 30-minute timeouts, CSRF protection, and comprehensive traffic analytics. I integrated the GitHub API to dynamically display my repositories and contribution activity, complete with intelligent caching to avoid hitting rate limits.

Design-wise, I created a modern developer aesthetic with a dark theme inspired by VS Code and GitHub Dark, using CSS variables throughout for maintainability. The navigation uses glass morphism effects with backdrop-filter blur, and every component follows a consistent design system with proper spacing, transitions, and hover states.

Code Highlights

Noteworthy implementations and solutions

Dual-User Database Security Architecture

Separate database connections for public (read-only) and admin (read/write) operations.

php - config.php
// PUBLIC PAGES - Read-Only Connection
// File: config.php
define('DB_USER', 'portfolio_viewer');
define('DB_PASS', '[redacted]');
// This user has SELECT-only permissions
// Even if SQL injection occurs, data cannot be modified

// ADMIN PAGES - Write-Capable Connection  
// File: admin_config.php (requires authentication first)
$db_user = $_SESSION['admin_db_user'];
$db_pass = $_SESSION['admin_db_password'];
// This user has full CRUD permissions
// Only accessible after admin_check.php validates session

$conn = new mysqli(DB_HOST, $db_user, $db_pass, DB_NAME);

💡 What Makes This Special

This is a defense-in-depth security pattern. By separating database privileges based on context, I prevent privilege escalation attacks. If someone exploits a SQL injection vulnerability on the public site, they only get read-only access. Write operations require BOTH authentication AND a separate database user with elevated privileges. This pattern is rare in portfolio projects but common in enterprise applications.

SQL Injection Prevention with Prepared Statements

Always use prepared statements with parameter binding to prevent SQL injection attacks.

php - manage_projects.php
// ❌ VULNERABLE - String concatenation (NEVER DO THIS)
$query = "SELECT * FROM projects WHERE id = " . $_GET['id'];
$result = $conn->query($query);
// An attacker can inject: id=1 OR 1=1-- to dump all data

// ✅ SECURE - Prepared statement with parameter binding
$stmt = $conn->prepare("SELECT * FROM projects WHERE id = ?");
$stmt->bind_param("i", $project_id);  // "i" = integer type
$stmt->execute();
$result = $stmt->get_result();
$project = $result->fetch_assoc();
$stmt->close();

// Parameter binding types:
// "i" - Integer
// "s" - String  
// "d" - Double/Float
// "b" - Blob

// Multiple parameters example:
$stmt = $conn->prepare("INSERT INTO projects (title, slug, is_featured) VALUES (?, ?, ?)");
$stmt->bind_param("ssi", $title, $slug, $is_featured);

💡 What Makes This Special

Prepared statements are THE gold standard for SQL injection prevention. The key is that user input is never interpreted as SQL code—it's treated purely as data. The database engine parses the query structure first, then inserts parameters, making injection impossible. I use this pattern religiously throughout the entire codebase—there isn't a single raw SQL concatenation anywhere in the project.

Advanced Rate Limiting with Browser Fingerprinting

Prevent contact form abuse using fingerprint hashing instead of IP addresses (Cloudflare-compatible).

php - submit_contact.php
// Generate unique fingerprint from session + headers
// Works behind CDNs like Cloudflare that strip real IPs
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$accept_lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
$accept_enc = $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '';

// Hash combines session ID with browser characteristics  
$fingerprint = hash('sha256', session_id() . '|' . $user_agent . '|' . $accept_lang . '|' . $accept_enc);

// Check rate limit: Max 2 submissions per 5 minutes
$stmt = $conn->prepare("
    SELECT COUNT(*) as count 
    FROM contact_rate_limit 
    WHERE fingerprint = ? 
    AND submitted_at > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
");
$stmt->bind_param("s", $fingerprint);
$stmt->execute();
$result = $stmt->get_result()->fetch_assoc();

if ($result['count'] >= 2) {
    http_response_code(429); // Too Many Requests
    echo json_encode(['success' => false, 'message' => 'Please wait before submitting again.']);
    exit;
}

// Store fingerprint for rate limit tracking
$stmt = $conn->prepare("INSERT INTO contact_rate_limit (fingerprint) VALUES (?)");
$stmt->bind_param("s", $fingerprint);
$stmt->execute();

💡 What Makes This Special

Traditional IP-based rate limiting breaks when using CDNs because all requests appear to come from the CDN's IP address. This fingerprinting approach identifies users based on browser characteristics instead. The SHA-256 hash ensures privacy (we don't store raw user agents), and combining multiple headers creates a unique signature. It's not 100% foolproof (sophisticated attackers can spoof headers), but it stops casual spam bots while working seamlessly with Cloudflare.

CSS Variables for Maintainable Design Systems

Using CSS custom properties to create a flexible, themeable design system with zero hardcoded values.

css - style.css
:root {
    /* Color System - Layered Background Depth */
    --bg-primary: #0d1117;      /* Main background (darkest) */
    --bg-secondary: #161b22;    /* Cards, sections */
    --bg-tertiary: #21262d;     /* Elevated elements */
    --bg-elevated: #2d333b;     /* Hover states, dropdowns */
    
    /* Text Hierarchy */
    --text-primary: #c9d1d9;    /* Headings, primary content */
    --text-secondary: #8b949e;  /* Body text, labels */
    --text-muted: #6e7681;      /* Metadata, descriptions */
    
    /* Accent Colors */
    --accent-blue: #58a6ff;     /* Primary CTA, links */
    --accent-green: #3fb950;    /* Success states */
    --accent-yellow: #d29922;   /* Warnings */
    --accent-red: #f85149;      /* Errors */
    
    /* Spacing Scale - Consistent Rhythm */
    --spacing-xs: 0.25rem;   /* 4px */
    --spacing-sm: 0.5rem;    /* 8px */
    --spacing-md: 1rem;      /* 16px */
    --spacing-lg: 1.5rem;    /* 24px */
    --spacing-xl: 2rem;      /* 32px */
    --spacing-2xl: 3rem;     /* 48px */
    --spacing-3xl: 4rem;     /* 64px */
    
    /* Typography */
    --font-primary: -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-mono: "Cascadia Code", "Source Code Pro", monospace;
}

/* Using the variables */
.card {
    background: var(--bg-secondary);
    border: 1px solid var(--border-primary);
    padding: var(--spacing-2xl);
    border-radius: var(--radius-lg);
    transition: border-color var(--transition-normal);
}

.btn-primary {
    background: var(--accent-blue);
    color: #000;
    padding: var(--spacing-md) var(--spacing-xl);
}

💡 What Makes This Special

CSS variables (custom properties) are the foundation of a maintainable design system. Instead of hardcoding #58a6ff throughout the codebase, I reference var(--accent-blue). This means changing the entire site's color scheme requires editing just ONE place. The spacing scale ensures visual consistency—every element uses multiples of the base unit. This is the same pattern used by design systems like Material Design and GitHub Primer. It makes the codebase infinitely more maintainable and makes theme switching trivial.

Dynamic Traffic Analytics Dashboard

Custom analytics system tracking page views, sessions, and traffic sources with Chart.js visualization.

javascript - manage_traffic.php
// Fetch analytics data via PHP
$stmt = $conn->prepare("
    SELECT 
        DATE(view_time) as date,
        COUNT(*) as views,
        COUNT(DISTINCT session_id) as sessions
    FROM page_views 
    WHERE view_time >= DATE_SUB(NOW(), INTERVAL ? DAY)
    GROUP BY DATE(view_time)
    ORDER BY date ASC
");
$stmt->bind_param("i", $days);
$stmt->execute();
$result = $stmt->get_result();

$dates = [];
$views = [];
$sessions = [];
while ($row = $result->fetch_assoc()) {
    $dates[] = $row['date'];
    $views[] = $row['views'];
    $sessions[] = $row['sessions'];
}

// JavaScript - Render with Chart.js
const ctx = document.getElementById('trafficChart').getContext('2d');
new Chart(ctx, {
    type: 'line',
    data: {
        labels: <?php echo json_encode($dates); ?>,
        datasets: [{
            label: 'Page Views',
            data: <?php echo json_encode($views); ?>,
            borderColor: 'rgb(88, 166, 255)',
            backgroundColor: 'rgba(88, 166, 255, 0.1)',
            tension: 0.4
        }, {
            label: 'Unique Sessions',
            data: <?php echo json_encode($sessions); ?>,
            borderColor: 'rgb(63, 185, 80)',
            backgroundColor: 'rgba(63, 185, 80, 0.1)',
            tension: 0.4
        }]
    },
    options: {
        responsive: true,
        maintainAspectRatio: false,
        scales: {
            y: { beginAtZero: true, ticks: { color: '#8b949e' } }
        },
        plugins: {
            legend: { labels: { color: '#c9d1d9' } }
        }
    }
});

💡 What Makes This Special

This analytics system demonstrates full-stack integration: PHP queries aggregate data from the database using GROUP BY for efficient counts, json_encode() safely passes data to JavaScript, and Chart.js renders responsive visualizations. The key insight is using COUNT(DISTINCT session_id) to track unique visitors versus total page views. The Chart.js configuration uses CSS variable colors (converted to RGB) to match the site's design system. This pattern scales to complex dashboards—I use the same approach for device stats, geographic data, and referral sources.

Key Takeaways

This project taught me the critical importance of security at every layer. I learned to never concatenate SQL queries (always use prepared statements), to escape all user output, and to implement rate limiting on user-facing endpoints. The fingerprint-based rate limiting system on the contact form was particularly interesting—I had to account for Cloudflare CDN stripping real IP addresses and create a hash-based approach using session IDs and user agents.

I also gained deep experience with database design, particularly understanding when to use soft deletes (is_active flags) versus hard deletes, how to structure many-to-many relationships (like project tags), and the importance of proper indexing for query performance.

On the frontend, I learned to build a truly responsive design without framework dependencies. The fluid typography using clamp() and auto-responsive grids with minmax() eliminate the need for manual breakpoints while ensuring the site looks perfect on any device.

Technical Highlights

Key technical achievements include:

**Dual-User Security Model**: Separate MySQL users for public (read-only) and admin (read/write) operations, preventing privilege escalation attacks.

**Advanced Traffic Analytics**: Custom-built analytics system tracking page views, visitor sessions, geographic data, device/browser stats, and referral sources. Includes Chart.js visualizations and time-range filtering.

**GitHub API Integration**: Asynchronous API calls with intelligent caching (configurable duration), displays repositories sorted by stars/forks/recent activity, and shows contribution timeline with commit counts.

**Rate Limiting**: Fingerprint-based rate limiting on contact form using SHA-256 hashing of session ID + user agent + headers, preventing spam without blocking legitimate users behind shared IPs.

**Professional Admin Panel**: Complete CMS with RBAC, sortable/filterable tables, AJAX form submissions, and a component library including toggle switches, data tables, stat cards, and professional tab navigation.

**CSS Variables & Design System**: Entire site uses CSS custom properties for colors, spacing, typography, and transitions. Zero hardcoded values, making theme changes trivial.

**Performance Optimizations**: Lazy loading for images, database query optimization with proper JOINs and GROUP BY, and cache-busting timestamps on static assets.

Interested in This Project?

I'd love to discuss this project in more detail or explore how similar solutions could benefit your team. Let's connect!