Writing a blog is more than just outputting words; for an engineer, the blog itself is an engineering project that undergoes continuous iteration and optimization. Since its inception, this site has evolved from simple static page generation to a highly automated system. Today, I’ll share the tech stack and engineering practices behind this blog.

🏗 Full-Stack Architectural Design

This site is built on Hugo and utilizes a fully containerized (Docker) deployment scheme. To ensure data sovereignty and minimalist operations, I opted for self-hosted services instead of Algolia or various third-party comment plugins.

Core Tech Stack

  • SSG: Hugo (PaperMod theme)
  • Web Server: Nginx (Alpine)
  • Comment System: Remark42 (Go-based, self-hosted)
  • Monitoring: Grafana + Loki (Log observability)
  • Deployment: Docker Compose
  • Automation Tools: Python + uv (for image processing and resource management)

System Architecture Diagram

graph TD User((Visitor)) --> FRP[FRP Public Tunnel] FRP --> Nginx{Nginx Reverse Proxy} Nginx --> Static[Static HTML Resources] Nginx --> Remark42[Remark42 Comment API] Nginx --> ImageHost[Self-hosted Nginx Image Host] Nginx -- JSON Log --> Loki[(Loki Log Store)] Loki --> Grafana[Grafana Dashboard] subgraph "Internal Docker Network" Static Remark42 ImageHost end

🚀 Key Engineering Practices

1. The Self-Reliant Comment System

After comparing Giscus (GitHub-based) and traditional Disqus, I chose Remark42.

  • Reason: It’s written in Go, extremely lightweight, and efficient. It supports one-click Docker deployment, stores data locally, doesn’t depend on third-party accounts, and is incredibly privacy-friendly.
  • Engineering Detail: Requests are proxied through Nginx via the /comments path, achieving cross-origin friendliness and SSL certificate sharing.

2. Visual Monitoring: Grafana and Log Analysis

To keep track of the blog’s health in real-time, I implemented visual monitoring by reading the logs under ../nginxlog.

  • Structured Logging: I defined a json_main format in the Nginx configuration. Compared to traditional text logs, JSON format allows the monitoring system to parse various fields (e.g., real IP, response time, User-Agent, etc.) without pain.
  • Monitoring Pipeline: Using Promtail to fetch the log directory in real-time and push it to Loki, which is then presented in Grafana. By configuring a dashboard, I can intuitively see:
    • A heat map of global traffic distribution.
    • Real-time curves of 4xx/5xx error codes (to timely detect malicious scanning).
    • PV/UV rankings of popular articles.

3. Automated Image Processing Pipeline

To solve the “choice paralysis” for cover images and SEO preview issues, I built a Python-based automation chain:

  • Automated Cover Generation (gen_cover.py): Uses the Pillow library to automatically fetch beautiful backgrounds from high-quality image libraries and synthesize clean covers based on the post’s title and tags.
  • Minimalist Image Management (manage_images.py):
    • Since I already have Nginx, why use a paid image host?
    • I mapped an /images path in Nginx. The management script syncs local images to the storage directory and generates Markdown links with a single command.

4. Production Environment via “Intranet Tunneling”

Since the blog is deployed on a local high-performance machine, I used FRP to establish a public tunnel.

  • Optimization: The real_ip module in Nginx parses the proxy_protocol passed by FRP to accurately obtain the visitor’s real IP. This is crucial for monitoring accuracy and the comment system’s anti-spam.

📈 SEO and Performance Tuning

Static blogs are fast by nature, but SEO can suffer without attention to detail. This site includes several optimizations:

  • JSON-LD Structured Data: Helps search engines understand the content.
  • Static Resource Caching: Long-term 30d caching enabled for images and static assets in Nginx.
  • 429 Rate Limiting: To prevent aggressive scraping, the limit_req module is configured with a reasonable burst buffer, ensuring a smooth experience for real users.

💡 Summary

A good personal blog should be easy to read, easy to write, and easy to maintain. Through these engineering practices, I’ve achieved a “build once, handle everything automatically” goal with complete data control and observability. Knowing that my code and words are on my own server provides a sense of security and control that no third-party platform can offer.

In the future, I will continue exploring AI-assisted content analysis and deeper automation chains, letting writing return to its pure essence.


Making progress every day.