add rate limiting, CSRF, newsletter, auto-checker, /uses and /projects pages
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
<a href="/admin/new" class="btn">New Post</a>
|
||||
<a href="/admin/status" class="btn btn-outline">Edit Status</a>
|
||||
<a href="/admin/uploads" class="btn btn-outline">Uploads</a>
|
||||
<a href="/admin/newsletter" class="btn btn-outline">Newsletter</a>
|
||||
<a href="/" class="btn btn-outline">View Site</a>
|
||||
<form method="POST" action="/admin/logout" class="inline-form">
|
||||
<button type="submit" class="btn btn-outline">Logout</button>
|
||||
|
||||
45
templates/admin/newsletter.html
Normal file
45
templates/admin/newsletter.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{{define "title"}}Newsletter — Admin{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="admin-wrap">
|
||||
<div class="admin-header">
|
||||
<h1>Newsletter Subscribers</h1>
|
||||
<div class="admin-actions">
|
||||
<a href="/admin" class="btn btn-outline">Back to Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .Flash}}<p class="flash-msg">{{.Flash}}</p>{{end}}
|
||||
|
||||
<p class="text-muted">{{.Count}} subscriber{{if ne .Count 1}}s{{end}}</p>
|
||||
|
||||
{{if not .Subscribers}}
|
||||
<p class="empty-state">No subscribers yet.</p>
|
||||
{{else}}
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Email</th>
|
||||
<th>Subscribed</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Subscribers}}
|
||||
<tr>
|
||||
<td>{{.Email}}</td>
|
||||
<td class="text-muted mono">{{formatDate .CreatedAt}}</td>
|
||||
<td class="actions-cell">
|
||||
<form method="POST" action="/admin/newsletter" class="inline-form"
|
||||
onsubmit="return confirm('Remove {{.Email}}?')">
|
||||
<input type="hidden" name="email" value="{{.Email}}">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Remove</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -49,6 +49,19 @@
|
||||
Pricing by project or hourly — contact me for details.
|
||||
</div>
|
||||
|
||||
<section class="subscribe-section">
|
||||
<h2>Stay updated</h2>
|
||||
<p>Occasional posts on OpenBSD, homelab builds, and infrastructure work. No spam.</p>
|
||||
<form method="POST" action="/newsletter" class="subscribe-form">
|
||||
<div class="hp-field" aria-hidden="true">
|
||||
<label for="url">URL</label>
|
||||
<input type="text" id="url" name="url" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
<input type="email" name="email" placeholder="your@email.com" required autocomplete="email">
|
||||
<button type="submit" class="btn btn-outline">Subscribe</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="contact-section">
|
||||
<h2>Get in touch</h2>
|
||||
<p>Tell me about your project or problem. I'll respond within one business day.</p>
|
||||
@@ -61,6 +74,12 @@
|
||||
{{if .Error}}<p class="form-error">{{.Error}}</p>{{end}}
|
||||
|
||||
<form method="POST" action="/hire" class="contact-form">
|
||||
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
||||
{{/* Honeypot: hidden from humans, bots fill it in */}}
|
||||
<div class="hp-field" aria-hidden="true">
|
||||
<label for="website">Website</label>
|
||||
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Name <span class="required-mark">*</span></label>
|
||||
<input type="text" id="name" name="name" value="{{.Name}}" required autocomplete="name" placeholder="Jane Smith">
|
||||
|
||||
87
templates/projects.html
Normal file
87
templates/projects.html
Normal file
@@ -0,0 +1,87 @@
|
||||
{{define "title"}}Projects — Ridgway Systems{{end}}
|
||||
{{define "meta-desc"}}Infrastructure projects and builds by Blake Ridgway — homelab, monitoring systems, security tooling, and more.{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="projects-page">
|
||||
<div class="page-header">
|
||||
<h1>Projects</h1>
|
||||
<p class="page-desc">Things built, broken, and rebuilt.</p>
|
||||
</div>
|
||||
|
||||
<div class="project-list">
|
||||
|
||||
<div class="project-item">
|
||||
<div class="project-header">
|
||||
<h2 class="project-title">ridgwaysystems.org</h2>
|
||||
<div class="project-tags">
|
||||
<span class="tag">Go</span>
|
||||
<span class="tag">OpenBSD</span>
|
||||
<span class="tag">self-hosted</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>This site. A single Go binary serving a blog, status page, hire page, and admin panel — no database, no Docker, no external dependencies at runtime. Flat Markdown files on disk, HMAC-signed sessions, chroma syntax highlighting. Deployed on OpenBSD behind relayd. The build log covers the whole thing.</p>
|
||||
<div class="project-links">
|
||||
<a href="/blog">Build log →</a>
|
||||
<a href="https://git.ridgwaysystems.org">Source →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-item">
|
||||
<div class="project-header">
|
||||
<h2 class="project-title">Policy-as-Code Firewall Framework</h2>
|
||||
<div class="project-tags">
|
||||
<span class="tag">pf</span>
|
||||
<span class="tag">IaC</span>
|
||||
<span class="tag">security</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>A policy-as-code system for managing pf firewall rules across multiple OpenBSD hosts. Rules defined in structured configuration, rendered to pf.conf via templating, with automated geo-location blocking and rule validation before deployment. Deployed at Triangle Insurance to manage ~200 rules across three firewall segments.</p>
|
||||
<div class="project-links">
|
||||
<a href="/blog/pf-vlans">Related post →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-item">
|
||||
<div class="project-header">
|
||||
<h2 class="project-title">ISP Network Monitoring</h2>
|
||||
<div class="project-tags">
|
||||
<span class="tag">Prometheus</span>
|
||||
<span class="tag">Grafana</span>
|
||||
<span class="tag">Go</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>Custom Prometheus exporter that continuously measures ISP throughput, latency, and packet loss across multiple WAN connections. Exports to Grafana for real-time dashboards and alerting. Replaced manual speed tests that only caught outages after users complained. Cut time-to-detect WAN degradation from hours to minutes.</p>
|
||||
</div>
|
||||
|
||||
<div class="project-item">
|
||||
<div class="project-header">
|
||||
<h2 class="project-title">Homelab Infrastructure</h2>
|
||||
<div class="project-tags">
|
||||
<span class="tag">OpenBSD</span>
|
||||
<span class="tag">Ansible</span>
|
||||
<span class="tag">Terraform</span>
|
||||
<span class="tag">homelab</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>The homelab: fw01 running OpenBSD with pf and WireGuard, two Dell rack servers, VLAN-segmented network (management, servers, IoT, guest), self-hosted Gitea, Matrix, Jellyfin, Prometheus, and Grafana. Fully documented, IaC'd where possible, and used as a test bed before anything touches production.</p>
|
||||
<div class="project-links">
|
||||
<a href="/infrastructure">Infrastructure diagram →</a>
|
||||
<a href="/uses">What I run →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-item">
|
||||
<div class="project-header">
|
||||
<h2 class="project-title">Zero-Touch Provisioning System</h2>
|
||||
<div class="project-tags">
|
||||
<span class="tag">PXE</span>
|
||||
<span class="tag">Ansible</span>
|
||||
<span class="tag">automation</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>PXE boot + Ansible-based provisioning pipeline for deploying standardized workstation images across Air Force Training bases. Reduced per-machine setup time by 75% and eliminated configuration drift between deployments. Machines boot, pull config from the server, and are production-ready without a human touching them after the initial PXE boot.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
99
templates/uses.html
Normal file
99
templates/uses.html
Normal file
@@ -0,0 +1,99 @@
|
||||
{{define "title"}}Uses — Ridgway Systems{{end}}
|
||||
{{define "meta-desc"}}Hardware, software, and tools Blake Ridgway uses in the homelab and day-to-day work.{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="uses-page">
|
||||
<div class="page-header">
|
||||
<h1>Uses</h1>
|
||||
<p class="page-desc">Hardware, software, and tools — homelab and daily driver.</p>
|
||||
</div>
|
||||
|
||||
<section class="uses-section">
|
||||
<h2>Hardware</h2>
|
||||
|
||||
<div class="uses-item">
|
||||
<div class="uses-item-header">
|
||||
<span class="uses-name">fw01</span>
|
||||
<span class="uses-role">Firewall / Router</span>
|
||||
</div>
|
||||
<p>SuperMicro 1U, Intel E3-1230v2, 16GB ECC RAM. Running OpenBSD. Handles all pf firewall rules, VLANs, WireGuard VPN, unbound DNS, and relayd reverse proxy. The critical piece everything else depends on.</p>
|
||||
</div>
|
||||
|
||||
<div class="uses-item">
|
||||
<div class="uses-item-header">
|
||||
<span class="uses-name">srv01</span>
|
||||
<span class="uses-role">Primary Services</span>
|
||||
</div>
|
||||
<p>Dell PowerEdge R720, dual Xeon E5-2600, 64GB RAM. Main workload server — runs Prometheus, Grafana, Gitea, OpenSMTPD, Matrix/Conduit. Loud and power-hungry, but handles everything without complaint.</p>
|
||||
</div>
|
||||
|
||||
<div class="uses-item">
|
||||
<div class="uses-item-header">
|
||||
<span class="uses-name">srv02</span>
|
||||
<span class="uses-role">Media / Secondary</span>
|
||||
</div>
|
||||
<p>Dell PowerEdge R710. Jellyfin media server, game server VMs, secondary storage, authoritative DNS (nsd). The workhorse for anything that doesn't need to be bulletproof.</p>
|
||||
</div>
|
||||
|
||||
<div class="uses-item">
|
||||
<div class="uses-item-header">
|
||||
<span class="uses-name">ws01</span>
|
||||
<span class="uses-role">Workstation</span>
|
||||
</div>
|
||||
<p>Desktop, AMD Ryzen. Daily driver for development, terminal sessions, and homelab management. Running Fedora Linux.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="uses-section">
|
||||
<h2>Operating Systems</h2>
|
||||
<ul class="uses-list">
|
||||
<li><strong>OpenBSD</strong> — fw01, this web server. Chosen for its security defaults, pf, and the fact that it does exactly what it says on the tin.</li>
|
||||
<li><strong>AlmaLinux / Rocky</strong> — srv01, srv02. RHEL-compatible for production workloads where SELinux and systemd are expected.</li>
|
||||
<li><strong>Fedora</strong> — Workstation. Stays close to bleeding-edge tooling without being Arch.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="uses-section">
|
||||
<h2>Networking</h2>
|
||||
<ul class="uses-list">
|
||||
<li><strong>pf</strong> — OpenBSD packet filter. VLANs, NAT, geo-blocking, antispoof. The whole reason fw01 runs OpenBSD.</li>
|
||||
<li><strong>WireGuard</strong> — VPN for remote access. Simple, fast, auditable.</li>
|
||||
<li><strong>unbound</strong> — Recursive DNS resolver on fw01. Validates DNSSEC, blocks ad/tracking domains.</li>
|
||||
<li><strong>nsd</strong> — Authoritative DNS on srv02 for the ridgwaysystems.org zone.</li>
|
||||
<li><strong>relayd</strong> — OpenBSD reverse proxy in front of this site and internal services.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="uses-section">
|
||||
<h2>Infrastructure & Automation</h2>
|
||||
<ul class="uses-list">
|
||||
<li><strong>Terraform</strong> — Cloud infrastructure (Azure, AWS). Anything that touches a cloud API gets IaC'd.</li>
|
||||
<li><strong>Ansible</strong> — Configuration management for Linux servers. Idempotent, no agent required.</li>
|
||||
<li><strong>Gitea</strong> — Self-hosted git at <a href="https://git.ridgwaysystems.org">git.ridgwaysystems.org</a>. Lightweight, fast, no subscription required.</li>
|
||||
<li><strong>Prometheus + Grafana</strong> — Metrics and dashboards for everything. Custom exporters for pf counters, ISP throughput, and hardware sensors.</li>
|
||||
<li><strong>Nagios</strong> — Service alerting. Opinionated but reliable — been running since before dashboards were cool.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="uses-section">
|
||||
<h2>Development</h2>
|
||||
<ul class="uses-list">
|
||||
<li><strong>VS Code</strong> — Primary editor. Remote SSH extension makes working directly on servers seamless.</li>
|
||||
<li><strong>Go</strong> — Preferred language for infrastructure tooling and this site. Fast to compile, easy to deploy a single binary.</li>
|
||||
<li><strong>Python</strong> — Scripting, automation, quick data processing.</li>
|
||||
<li><strong>Bash / ksh</strong> — Bash on Linux, ksh on OpenBSD. Shell scripts for anything that doesn't need to outlast the week.</li>
|
||||
<li><strong>tmux</strong> — Terminal multiplexer. Multiple panes across multiple SSH sessions, always.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="uses-section">
|
||||
<h2>Self-hosted Services</h2>
|
||||
<ul class="uses-list">
|
||||
<li><strong>OpenSMTPD</strong> — Mail server. Handles inbound and outbound for ridgwaysystems.org.</li>
|
||||
<li><strong>Matrix / Conduit</strong> — Self-hosted chat. Federated, encrypted. Currently migrating.</li>
|
||||
<li><strong>Jellyfin</strong> — Media server. No subscription, no phone-home, streams anywhere on the LAN.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user