Deploy a Static Hugo Blog with Podman, Envoy Sidecar, and Systemd
This guide explains how to replace Docker with Podman for hosting a static Hugo site, using a sidecar Envoy proxy, shared network namespaces, Kubernetes‑compatible pod definitions, and systemd services to achieve automatic startup and reliable service discovery.
Podman originated as part of the CRI‑O project and was later split into the independent libpod project; unlike Docker, it runs without a daemon, so container processes are direct children of the Podman CLI.
Podman launches containers via the OCI runtime runc in a fork/exec model, which offers several advantages: administrators can identify the exact process that started a container, apply cgroup limits, receive systemd notifications via SD_NOTIFY, and use socket activation.
Deploying a static Hugo blog with a sidecar Envoy
The deployment consists of two Envoy layers and a Hugo‑generated static site served by nginx. The front‑end Envoy provides an entry point, while a sidecar Envoy runs in the same network namespace as the nginx container.
Creating a pod and running containers
$ podman pod create --name hugo $ podman pod ls $ podman run -d --pod hugo nginx:alpine $ podman psTo inspect the pod and its containers, use podman pod top hugo and podman ps -ap.
Exporting a Kubernetes manifest
$ podman generate kube hugo > hugo.yamlThe generated hugo.yaml can be applied with kubectl apply -f hugo.yaml or deployed directly with podman play kube hugo.yaml.
Service discovery challenges
When using declarative pod definitions, automatic service discovery is unavailable without a CNI plugin that provides static IPs; such plugins often require an etcd backend, which may be undesirable on resource‑constrained VPS hosts.
Running containers with explicit networking
$ podman run -d --name hugo \
--ip=10.88.0.10 \
-v /opt/hugo/public:/usr/share/nginx/html \
-v /etc/localtime:/etc/localtime \
nginx:alpine $ podman run -d --name hugo-envoy \
-v /opt/hugo/service-envoy.yaml:/etc/envoy/envoy.yaml \
-v /etc/localtime:/etc/localtime \
--net=container:hugo envoyproxy/envoy-alpine:latestThe service‑envoy.yaml file defines listeners, clusters, and routes for the sidecar proxy (full YAML omitted for brevity).
Understanding Podman internals
Podman consists of the CLI and a container runtime managed by conmon, which handles monitoring, logging, TTY allocation, and out‑of‑memory events. conmon acts as the parent process for all containers, allowing systemd tools such as systemctl to inspect resource usage.
Creating systemd services for automatic start
[Unit]
Description=Podman Hugo Service
After=network.target network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/podman start -a hugo
ExecStop=/usr/bin/podman stop -t 10 hugo
Restart=always
[Install]
WantedBy=multi-user.targetSimilar unit files are created for the sidecar Envoy ( hugo‑envoy_container.service) and the front‑end Envoy ( front‑envoy_container.service). After stopping the containers with podman stop $(podman ps -aq), the services are started and enabled with systemctl start … and systemctl enable …, ensuring they launch on boot.
Conclusion
Migrating a static blog from Docker to Podman involves creating pods, sharing network namespaces, configuring sidecar Envoy proxies, handling service discovery without Docker‑style DNS, and managing containers via systemd. Although the process can be intricate, it demonstrates Podman's suitability for Kubernetes‑native workflows on lightweight hosts.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
