From Lumière to a Live Site: A Homelab Journey
This website is my personal corner of the internet. My preciousss... We wants it, we needs it! And because it's so precious, it's built with a focus on simplicity and ease of maintenance.
Heh heh heh! Unveiling the Mechanics
At its core, this site is powered by Hugo. I write all my content in “simple Markdown files”, and Hugo transforms them into lightweight, HTML pages. This approach means no databases, just choo-choo-choo, blazing-fast content delivery. It’s perfect for a personal site where performance and ease of maintenance are key.
My Homelab: A Descent into the Suffering of Self-Hosting
Instead of relying on external hosting providers, this site lives on my very own homelab. It’s a mini-PC humming away, quietly asserting its dominance over my projects. This isn’t just about hosting; it’s a continuous learning failing experience and a way to experiment with self-managed infrastructure.
Deployment: Docker and Dokploy
So, how does this digital preciousss escape my lair and reach the masses? Through a deployment process that’s… well, let’s just say it gets the job done:
Dockerfile: This little text file is the recipe for my Docker image, defining how my site is built and served.
##################################################################### # Build Stage # ##################################################################### # Use the 'exts' image which includes Hugo Extended and Node.js. FROM [hugomods/hugo:exts](https://hub.docker.com/r/hugomods/hugo) AS builder # Set the working directory for the build. WORKDIR /src # First, copy only the package files and install dependencies. # This leverages Docker caching, so 'npm ci' only runs when package files change. COPY package*.json ./ RUN npm ci # Now, copy the rest of your source code. COPY . . # Run your custom build command. This will execute "hugo && pagefind --source public" # as defined in your package.json. RUN npm run build ##################################################################### # Final Stage # ##################################################################### # Use the lightweight Nginx-only image for the final container. FROM [hugomods/hugo:nginx](https://hub.docker.com/r/hugomods/hugo) # Copy the generated static files from the 'builder' stage's /src/public directory # into the final image's webroot, which is '/site'. COPY --from=builder /src/public /siteThis
Dockerfileuses a multi-stage build process:Build Stage: It starts with a hugomods/hugo image (which includes Hugo and Node.js). It copies
package.jsonandpackage-lock.jsonto install Node.js dependencies efficiently (leveraging Docker’s build cache). Then, it copies the rest of your project and runsnpm run build(which typically executeshugoandpagefindto generate your static site).Final Stage: A much lighter hugomods/hugo image is used. It copies only the built static files from the
publicdirectory of thebuilderstage into the Nginx webroot (/site). This keeps the final Docker image small and secure, containing only what’s necessary to serve the website.Dokploy: This is an open-source, self-hosted deployment platform. It automates the process of picking up changes from Git, building Docker images, and deploying them to a server, handling tasks like reverse proxying and SSL.
In short, I write, Hugo builds, Docker packages, and Dokploy deploys – all on my own hardware. Now, if you’ll excuse me, my gaming backlog isn’t going to clear itself, and I have a Monolith to conquer, a tainted path leading directly to the Paintress!