-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture and Internals
How the image is built and what happens when the container starts.
| Layer | What |
|---|---|
| Base | Alpine Linux |
| Init / supervisor | s6-overlay |
| VPN | ocserv (built from source) |
| Firewall backend | nftables (nft) |
| Build system | Meson + Ninja |
The Dockerfile uses several stages so the final image stays small and contains no build tooling:
-
ocserv-build— installs build deps and compiles ocserv from the upstream tarball with Meson/Ninja. Built with the nftables firewall-script backend. Installs into a staging prefix (/pkg). The bundled defaultocserv.conftemplate is derived from ocserv'sdoc/sample.configwith certificate paths normalized to/etc/ocserv/.... -
s6-fetch— downloads the architecture-appropriate s6-overlay release tarballs (it maps Docker'sTARGETARCHto s6's arch names, so the image is multi-arch). -
rootfs— assembles the container root filesystem: the project'srootfs/overlay (s6 service definitions, helper scripts), the s6-overlay files, and the compiled ocserv from/pkg. Permissions are normalized here. -
Final runtime — Alpine + just the runtime libraries (gnutls, libev, nftables, etc.), then the assembled rootfs copied in.
ENTRYPOINTis s6's/init.
Pinned, reproducible apk versions are used throughout. The base image and package versions are kept current by a maintenance workflow (see Building and CI).
s6-overlay runs the service tree under /etc/s6-overlay/s6-rc.d. Three services matter:
init-config ─┐
├─► svc-ocserv (longrun)
init-nat ────┘
Oneshot. Ensures /etc/ocserv/ocserv.conf exists — if it's missing, it copies the bundled template into place. Your own mounted config is never overwritten.
Oneshot. Prepares networking:
- Enables IPv4 forwarding (and IPv6 forwarding if
IPV6_FORWARD=1). If IPv4 forwarding can't be enabled, it logs guidance and stops (the container needs theip_forwardsysctl). - Installs the
table inet ocservnftables rules: a forward chain for the tunnel interface and a postrouting masquerade forVPN_SUBNETviaWAN_IF. Optionally IPv6 masquerade whenIPV6_NAT=1. See Networking NAT and Routing.
Longrun, depends on both oneshots. Creates runtime dirs (/run/ocserv, …) and execs:
ocserv --foreground --config /etc/ocserv/ocserv.conf --log-stderr
Logs go to the container's stdout/stderr, so docker logs shows everything.
All env-var defaults live in one helper, /usr/local/bin/backend-functions, which the service scripts source. That's where VPN_SUBNET, WAN_IF, VPN_IF, IPV6_* defaults and the logging helpers are defined. See Configuration Reference.
| Path | Role |
|---|---|
/etc/ocserv/ocserv.conf |
Main config (your volume) |
/etc/ocserv/ocpasswd |
User database (your volume) |
/usr/share/ocserv/ocserv.conf.template |
Bundled default config |
/usr/sbin/ocserv, /usr/sbin/ocserv-worker
|
The server |
/usr/bin/occtl, /usr/bin/ocpasswd
|
Control + user tools |
/usr/libexec/ocserv-fw |
Per-user firewall helper (nftables) |
/run/ocserv/ |
PID + control sockets |
/swag-config/ |
Optional read-only SWAG certs |
Next: Building and CI · Troubleshooting
ocserv-server · MIT License · Built on ocserv + s6-overlay