Skip to main content
Advanced Search
Search Terms
Content Type

Exact Matches
Tag Searches
Date Options
Updated after
Updated before
Created after
Created before

Search Results

190 total results found

The front door

Edge Networking with pfSense

Everything that's reachable from the outside world passes through one VM: a pfSense firewall/router (10.100.100.1 inside, a public IP outside). It wears three hats: Router/NAT — gives the private 10.100.100.0/24 VMs a way out to the internet, and is the defau...

NAT: how private VMs reach the world

Edge Networking with pfSense

The VMs live on a private range that isn't routable on the internet. They still need to fetch packages, pull container images, and so on. pfSense handles that with outbound NAT: as a VM's traffic leaves for the internet, pfSense rewrites the source to its own ...

HAProxy: one door, many rooms

Edge Networking with pfSense

All the web services share a single public IP, so something has to look at each incoming request and send it to the right backend. That's HAProxy, running on pfSense, routing by hostname: https://git.example.com -> GIT-Server 10.100.100.2:3000 htt...

TLS terminates here, once

Edge Networking with pfSense

There is exactly one place in the whole lab that deals with certificates: HAProxy on pfSense. It holds a wildcard certificate for *.example.com and terminates TLS for every service. Behind it, traffic to the backends is plain HTTP on the trusted private networ...

A gotcha that cost an afternoon

Edge Networking with pfSense

A war story, because the lessons that stick are the ones that bit you. A backend's address was changed in the HAProxy GUI, Apply was clicked, and… HAProxy kept sending traffic to the old port. The config on disk said one thing; the running proxy did another. B...

Why a jump host

The SSH Bastion (Jump Host)

None of the internal VMs accept SSH from the internet. There's exactly one machine you can SSH to from outside — the jump host (or bastion) at 10.100.100.254, which also holds a public address. From there, you hop to anything internal. you --SSH--> Jump host...

The ProxyJump pattern

The SSH Bastion (Jump Host)

You don't want to manually SSH to the bastion and then SSH again — that's clumsy and breaks tooling. SSH has a built-in feature for exactly this: ProxyJump (and its lower-level cousin, ProxyCommand). It transparently tunnels your connection to the internal hos...

Hardening, and a host-key surprise

The SSH Bastion (Jump Host)

Because the bastion is the one publicly-reachable SSH endpoint, it's the one that gets the most attention: keep it patched, restrict who can log in, prefer keys, watch its auth logs (they ship to the central log store like everything else). A surprise worth wr...

Lessons on bastion access

The SSH Bastion (Jump Host)

One way in. Internal VMs expose no SSH to the internet; the bastion is the single public SSH endpoint. ProxyJump makes it painless. Bastion-only access with none of the two-hop hassle — tooling included. Harden the one box hard. It's the door everyone uses; p...

Why golden images

Golden-Image VM Provisioning

There are ~15 VMs in this lab. Not one of them was installed from an ISO by hand. Every single one is a clone of a single golden image — one carefully prepared template — customised at first boot by cloud-init. The alternative (install Ubuntu by hand, fifteen ...

The template

Golden-Image VM Provisioning

The template is one VM (ID 9999) prepared once: a current Ubuntu cloud image, the QEMU guest agent, the logging agent, sensible defaults — and then turned into a Proxmox template so it can only be cloned, not run directly. A few things are deliberately baked i...

Injecting per-VM identity with cloud-init

Golden-Image VM Provisioning

Cloning gives you fifteen identical machines. Cloud-init is what makes each one itself on first boot — its hostname, its IP, its login. The flow for creating a VM here is a small, repeatable recipe: 1. clone the template (9999) -> new VM with the next free I...

Grow-on-first-boot, and a clean teardown

Golden-Image VM Provisioning

Two finishing touches make the recipe pleasant to live with. Disks grow to fit. The template's disk is small. When you clone and resize the new VM's disk to, say, 250 GiB, cloud-init's growpart/resize on first boot expands the filesystem to fill it automatical...

Lessons on provisioning

Golden-Image VM Provisioning

One golden image, cloned many times. Consistency first; it kills "works on that box" bugs. Bake the common, inject the unique. Shared tooling in the template; hostname/IP/credentials via cloud-init. Have an address convention. "IP = VM-ID minus 100" removes a...

Why a baseline at all

Ubuntu VM Baseline & Tuning

Every VM in the lab gets the same small set of OS-level adjustments before it does any real work. Not a heavy "hardening framework" — just a handful of settings that make a virtual machine on virtualised, SSD-backed storage behave sensibly. The value isn't any...

What's in the baseline

Ubuntu VM Baseline & Tuning

The recurring adjustments, and the reasoning for each: Swap — present and small on the general VMs as a safety cushion, but off on the Kubernetes nodes (the kubelet wants it gone). The point isn't "swap good" or "swap bad" — it's matching the swap policy to t...

Lessons on the baseline

Ubuntu VM Baseline & Tuning

Tune to the role, not dogmatically. Swap off for k8s nodes, on (small) elsewhere. BBR where it faces the internet. There's no single right answer for the whole fleet. Apply it the same way everywhere. The benefit is uniformity; a baseline that's applied to 13...

Why self-host Git

Self-hosted Git with Gitea

Git is distributed, but teams still need a central place to push to, open pull requests, and trigger automation. You could use a SaaS forge — or you could run your own. This lab runs Gitea (GIT-Server, 10.100.100.2), a lightweight open-source Git forge. The re...