jmurphyau.com
Theme

This site

Between you and this page, and between your email and my inbox: one Swift process at my home, hosted on a Superloop NBN connection. Every layer, below.

Design →   Your browser →

01

The host

One machine, in Melbourne.

One computer at home runs all of it: web, mail, DNS, certificates and the question box’s language model.

CPU
AMD Ryzen 5 5600X6 cores, 12 threads
Memory
16 GB
GPU
NVIDIA RTX 309024 GB, for the question box
System
Ubuntu 26.04 LTSLinux 7.0
Connection
Superloop NBNAS38195
Software
OriginKitSwift 6.4, 91,000 lines, 1,747 tests
02

Addresses

IPv4 and IPv6, with reverse DNS.

Superloop routes IPv6 here, so IPv6 connections reach the process directly. IPv4 is one address behind the gateway. Every name has A and AAAA; the server refuses a zone otherwise.

IPv6
2401:d002:3a0c:1500:2::1reverse: mail.jmurphyau.com
IPv4
36.255.114.31NAT at the gateway
Reverse DNS
served herethe IPv6 zone, delegated to this machine
03

The firewall

The gateway, then the host.

The gateway forwards only served ports. On the host, nftables drops everything else inbound; SSH only from the LAN. Outbound, the server may reach DNS, TCP 25, 443 and 993, and nothing else: never loopback, private ranges or the LAN.

Inbound TCP
25 · 53 · 80 · 443 · 465 · 993served addresses only
Inbound UDP
53 · 443DNS and QUIC
Outbound
DNS · 25 · 443 · 993nothing else
SSH
LAN only
04

Sockets

From systemd, handed on after a peek.

systemd binds every port and passes the sockets in; OriginKit never binds a port or holds a capability. One binary, two roles: supervisor and worker, each its own Unix user. Over IPv4 the supervisor peeks at a connection’s first bytes and hands the socket to the worker with SCM_RIGHTS. Over IPv6 it goes straight to the worker.

TLS ports
ClientHello SNI
Port 80
Host header
Port 53
DNS question
UDP 443
QUIC Initialdecrypted with the public RFC 9001 keys
Port 25
STARTTLS ClientHelloafter SMTP up to RCPT TO
05

No privileges

Nothing as root, nothing it doesn’t need.

The worker runs as ok-jmurphyau with no capabilities, a seccomp filter, W^X memory, a read-only filesystem and no devices. It can write only its own directory.

Two slots: a new build starts in the idle one and takes new connections; the old one drains and exits. Measured: 18 swaps under load at 17,200 requests a second, no failed requests.

Capabilities
noneCapBnd = 0, NoNewPrivs
System calls
@system-serviceminus @privileged and @resources
Memory
66 MBworker RSS
Filesystem
read-onlyexcept its own directory, mode 0700
Containers
nonesystemd units
06

TLS

1.2 minimum, post-quantum key exchange.

OpenSSL 3.5, server preference. ECDHE only; AES-GCM or ChaCha20-Poly1305; signatures SHA-256 or stronger; no renegotiation, no compression. Modern browsers get post-quantum X25519MLKEM768. One ECDSA P-256 certificate per name, chosen by SNI.

Versions
TLS 1.3 · TLS 1.2
Key exchange
X25519MLKEM768post-quantum hybrid
TLS 1.3 suites
AES-256-GCM · ChaCha20-Poly1305 · AES-128-GCM
TLS 1.2 suites
ECDHE-ECDSA · ECDHE-RSAsame three ciphers
Certificates
ECDSA P-256one per name
07

HTTP

HTTP/1.1 and HTTP/3, both in Swift.

HTTP/1.1 is OriginKit’s own. HTTP/3 runs on Apple’s swift-network-evolution QUIC engine, with OriginKit’s listener, framing and QPACK; each request goes to the same handler. Port 80 answers 308 to HTTPS. Load-tested on the host: 27,600 requests a second for the home page, no failures.

Versions
HTTP/1.1 · HTTP/3
QUIC
swift-network-evolutionApple’s engine, 0.4.0
Cache
64 MB, W-TinyLFUETag, 304
Compression
gzipbodies ≥ 1 KiB
Load test
27,600 req/sp50 1.1 ms · p99 3.0 ms · 32 clients, 3 × 8 s, on the host
This page
HTTPS
08

DNS

Authoritative, from the same process.

The .com registry delegates jmurphyau.com to ns1 and ns2.jmurphyau.com: both this process. The IPv6 reverse zone is answered from the same machine. ANY gets the RFC 8482 answer. Zone transfers and NOTIFY are built in; DNSSEC is not, yet.

Zones
jmurphyau.com · the IPv6 reverse
Records
A · AAAA · NS · CNAME · PTR · MX · SRV · SOA · TXT · CAA
Rate limit
20/s, burst 40UDP, per /24 or /56
CAA
letsencrypt.org; no wildcards
Reload
live, inotify
09

Certificates

Let’s Encrypt, for names and IP addresses.

OriginKit’s own ACME client. Names use dns-01, answered by its own DNS. IP addresses use http-01 on Let’s Encrypt’s six-day profile; that certificate goes to clients that send no SNI. Before each order it checks that a public resolver sees its SOA serial and only its addresses.

The domain has its own client CA, name-constrained to its email addresses, and passkey sign-in on OriginKit’s own WebAuthn.

Authority
Let’s EncryptRFC 8555, own client
Names
dns-01one certificate each
Addresses
http-01, RFC 87386-day, IPv4 and IPv6
Renewal
at ⅔ of lifeevery ~4 days for IPs
Client CA
ownname-constrained, to 2036
10

Mail

SMTP in, SMTP out, IMAP to read it.

Mail to james@jmurphyau.com arrives at the same process on port 25. It checks SPF, DKIM and DMARC, and stores each message as one .eml file; no database. I read it over IMAP with a client certificate. Outgoing mail is DKIM-signed and retried for five days.

Ports
25 STARTTLS · 465 · 993
DKIM
RSA 2048rsa-sha256, relaxed/relaxed
SPF
-allthis server’s addresses only
DMARC
p=quarantinestrict alignment
Login
client certificateSASL EXTERNAL, or app password
11

The question box

A language model on the same machine.

Ask runs Qwen3-8B on the RTX 3090: 1,600 lines of Swift, no package dependencies, CUDA opened with dlopen. My notes are prefilled once into the KV cache; no retrieval. The service has no network; the web worker reaches it over a Unix socket. Questions are rate-limited and not logged.

Model
Qwen3-8Bbf16, 15.6 GB of weights
Speed
39.8 tokens/s
Context
12,230 tokensmy notes, prefilled once
Network
nonea Unix socket from the web worker
12

The pages

Plain files, written with AI.

Static files: HTML, one stylesheet, a few small JavaScript modules. No framework, build step, web fonts, cookies or trackers. Claude Code wrote them, with me directing. A deploy is a file rename; nothing restarts.