Skip to content

ServerAdmin Guide

Bradley Brown edited this page Aug 13, 2026 · 1 revision

Server Admin Guide

Deploying, hardening, and managing the Fracturing Fog headless render server.

Server Admin dialog — running server, default request limits, first heartbeat received.


Table of Contents

  1. Overview
  2. First Server Launch
  3. Server Admin Dialog
  4. CLI Flags
  5. Self-Signed Cert Bundle
  6. Production PKI Deployment
  7. TLS Hardening
  8. Rate Limiting + Concurrency
  9. Resource Limits
  10. Stale Work Sweep
  11. Forbidden Fractal Types
  12. Protocol Layer Validators
  13. Logs + Monitoring
  14. Status Bar Indicator
  15. Troubleshooting

1. Overview

FracturingFog.exe --server runs a headless render worker that accepts mTLS-protected render jobs and streams results back over the same TLS channel. The same EXE serves three roles:

Mode Invocation
UI FracturingFog.exe (default Avalonia shell)
Server FracturingFog.exe --server [opts]
Remote batch client FracturingFog.exe --batch --remote …

The server has no UI surface of its own — it logs to stdout + %APPDATA%\FracturingFog\server-logs\ and is managed via the Server Admin dialog in the UI shell (for local servers) or via SSH + CLI flags (for remote hosts).


2. First Server Launch

FracturingFog.exe --server

On first run, with no explicit cert paths:

  1. Creates %APPDATA%\FracturingFog\server-certs\ if missing.
  2. Generates a self-signed ca.pfx, server.pfx, client.pfx bundle (passwordless).
  3. Writes a default server-config.json next to the certs dir.
  4. Binds 127.0.0.1:47823 (loopback only — fresh installs are NOT LAN-exposed by default).
  5. Logs listening on 127.0.0.1:47823 (loopback only — use --bind 0.0.0.0 to expose).

The Avalonia shell's status bar shows a green ● Server pill on the right edge once the server is up.


3. Server Admin Dialog

Floating Menu → Server… opens the admin dialog. The dialog manages only the local --server process; remote servers must be managed on their own hosts.

Sections

Status

  • Uptime
  • In-flight job count
  • Completed job count (this session)
  • Last error string (hover for full message)
  • Current bind / port / queue depth

Lifecycle

  • Start — spawn a child FracturingFog.exe --server process using the saved config.
  • Restart — request a soft-restart on the next idle window. Pending config edits apply.
  • Kill — terminate the child process immediately (drops in-flight jobs).

Bind / Port

  • Bind address (default 127.0.0.1). Set to 0.0.0.0 for LAN, or to a specific NIC.
  • Port (default 47823).

Limits

  • Max minutes per job (default 240).
  • Allow client to request a longer timeout (capped server-side regardless).
  • Queue depth (default 1; excess connections receive busy).
  • Max concurrent TLS sessions (default 32).

Rate limit (per-IP)

  • Accepted-connection rate per minute (default 0 = disabled).
  • Burst allowance (default 10).

TLS hardening

  • Require TLS 1.3 only (default off).
  • Revocation check mode: none (default; appropriate for self-signed dev bundle) / online / offline.
  • Allowed client cert thumbprints — when non-empty, presented client cert must additionally match one of these (chain trust is still required).

Paths

  • Server cert PFX path (override the auto-generated server.pfx).
  • Client CA PFX path (override the auto-generated ca.pfx).
  • Cert directory (lower precedence than the per-file paths).
  • Log directory.
  • Work directory.

Stale sweep

  • Work-dir auto-purge age (default 1 h; 0 disables). Leftover job-* subdirs older than this delete on startup.

Apply rewrites server-config.json and signals the running server to soft-restart on the next idle window. Cancel discards in-memory edits.


4. CLI Flags

All admin dialog fields are reachable via flags so the server runs unattended on machines without UI access.

Flag Default Meaning
--bind ADDR 127.0.0.1 Listen interface
--port N 47823 TCP port
--max-minutes N 240 Per-job time ceiling
--allow-override off Client may request longer timeout (still capped)
--queue-depth N 1 Queue depth (excess connections receive busy)
--cert PATH auto Server identity PFX path
--client-ca PATH auto CA used to validate client certs
--log-dir PATH %APPDATA%\FracturingFog\server-logs\ Log dir
--work-dir PATH %APPDATA%\FracturingFog\server-work\ Job scratch dir
--config PATH %APPDATA%\FracturingFog\server-config.json Override config-file path

Flags override file values for the current process. Restart uses the file values again unless flags are passed.

Example for a public render host:

FracturingFog.exe --server ^
    --bind 0.0.0.0 ^
    --port 47823 ^
    --max-minutes 60 ^
    --queue-depth 4 ^
    --cert C:\pki\server-myhost.pfx ^
    --client-ca C:\pki\client-ca.pfx ^
    --log-dir D:\fflog

5. Self-Signed Cert Bundle

The auto-generated bundle is convenient for loopback + small LAN deployments. Three files in %APPDATA%\FracturingFog\server-certs\:

File Purpose Distribute to
ca.pfx Trust root Every client (placed as ""Server CA"" in Client dialog)
server.pfx Server identity The server only
client.pfx Default client identity Every client (placed as ""Client cert"")

Dev certs have no passwordCert password field is blank.

For loopback (single machine):

  1. Run FracturingFog.exe --server once.
  2. Client dialog → Client cert → %APPDATA%\FracturingFog\server-certs\client.pfx.
  3. Client dialog → Server CA → %APPDATA%\FracturingFog\server-certs\ca.pfx.
  4. Save the connection.

For LAN (different machines):

  1. On the server host: FracturingFog.exe --server --bind 0.0.0.0.
  2. Copy client.pfx + ca.pfx to each client over a trusted channel (encrypted USB, SCP, Bitlocker share — never email).
  3. On each client, browse to the copies in the Client dialog.

6. Production PKI Deployment

For multi-user deployments, replace the self-signed bundle with certs issued by your own CA.

Issue per-user client certs

openssl req -new -newkey rsa:4096 -nodes \
    -keyout alice.key -out alice.csr \
    -subj ""/CN=alice@example.com""

openssl x509 -req -in alice.csr \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -out alice.crt -days 365 -sha256

openssl pkcs12 -export \
    -inkey alice.key -in alice.crt -certfile ca.crt \
    -out alice.pfx -name ""Fracturing Fog client (alice)"" \
    -passout pass:""STRONG-PASSWORD""

Repeat for each user. Distribute alice.pfx only to Alice; give every user ca.pfx (or just the public ca.crt).

Issue the server cert

openssl req -new -newkey rsa:4096 -nodes \
    -keyout fog-server.key -out fog-server.csr \
    -subj ""/CN=fog.example.com""

openssl x509 -req -in fog-server.csr \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -out fog-server.crt -days 365 -sha256 \
    -extfile <(printf ""subjectAltName=DNS:fog.example.com,IP:10.0.0.42"")

openssl pkcs12 -export \
    -inkey fog-server.key -in fog-server.crt -certfile ca.crt \
    -out fog-server.pfx -name ""Fracturing Fog server"" \
    -passout pass:""STRONG-PASSWORD""

Configure the server

FracturingFog.exe --server ^
    --bind 0.0.0.0 ^
    --cert C:\pki\fog-server.pfx ^
    --client-ca C:\pki\ca.pfx

Cert password handling for password-protected PFX files: pass the password via the Windows Credential Manager (preferred) or as a separate config field — never hard-code in plaintext config.

Configure each client

In the Client dialog:

  • Client cert → alice.pfx.
  • Server CA → ca.pfx.
  • Cert password → the password used during openssl pkcs12 -export.
  • The first save of a connection with a non-empty cert password sets the master password for the local vault. All subsequent sessions must enter the same master password to decrypt.

7. TLS Hardening

The server defaults to TLS 1.2+1.3, revocation check none. Hardening options:

Require TLS 1.3

""requireTls13"": true

Drops support for TLS 1.2's deprecated ciphersuites + RSA key exchange. Modern clients support 1.3 since 2018; older Windows-only deployments may need 1.2 for legacy .NET clients.

Revocation policy

""revocationCheckMode"": ""online""    // CRL / OCSP fetched per handshake
""revocationCheckMode"": ""offline""   // Cached CRL only
""revocationCheckMode"": ""none""      // No check (self-signed dev default)

online requires the server to reach the CRL distribution point during handshake. Slower but catches revoked certs immediately.

Cert pinning (thumbprint allowlist)

""allowedClientThumbprints"": [
    ""3A:7B:1C:..."",
    ""5F:DE:90:...""
]

When non-empty, the presented client cert thumbprint must match one of these in addition to chaining to the configured CA. Lets you issue many certs from one CA but only authorize a subset.

Thumbprint comparison is hex, case-insensitive, with spaces / dashes ignored.


8. Rate Limiting + Concurrency

Per-IP rate limiter

Sustained accepted-TCP-connection rate per remote IP per minute. 0 disables.

""rateLimitPerMinute"": 30,
""rateLimitBurst"": 10

Burst lets a legitimate reconnect loop / UI startup wave through without penalty. Sustained = stricter; burst = forgiving short spikes.

Hits over the rate cause the TCP accept to close immediately with no TLS handshake — costs the attacker resources, costs you almost nothing.

Max concurrent TLS sessions

""maxConcurrentConnections"": 32

Hard ceiling regardless of rate-limit state. Default 32 — comfortable for small LAN deployments. Public-facing servers should raise it to a sustainable level (depends on CPU / RAM headroom).

Queue depth

""queueDepth"": 4

How many render jobs may be queued behind the in-flight one. Excess connections receive a protocol-level busy reply. Default 1 — one in-flight + zero queued. Match to per-job render time and expected throughput.


9. Resource Limits

Per-job time ceiling

""maxMinutes"": 60,
""allowOverride"": false

A render exceeding maxMinutes is cancelled. allowOverride lets the client request a longer cap (still capped server-side at maxMinutes).

Image size cap

Hard-coded at the protocol validation layer:

Dimension Hard cap
Width / Height 32768 px
Total pixels 64 megapixels
Video seconds 0.5 – 600
Video fps 1 – 240

Requests exceeding these are rejected with bad-request.

Memory pressure

The server allocates an int[Width * Height] escape buffer per job + a byte[Width*Height*4] BGRA output buffer + per-thread DD/QD scratch. A 32k × 32k render at Extreme quality holds ~5 GB resident plus working set. Match queueDepth to your headroom.


10. Stale Work Sweep

""workDirStaleHours"": 1.0

On startup, the server walks %APPDATA%\FracturingFog\server-work\, deletes any job-* subdir older than this age. 0 disables the sweep.

Default 1 hour — anything older than that is from a previous crash or kill and is safe to discard.

If a job is in progress when the server is killed, its work dir is left intact for forensic inspection until the next startup's sweep.


11. Forbidden Fractal Types

The protocol layer blocks three fractal types from server-side rendering:

  • UserEquation — Roslyn-compiled C# = RCE.
  • Sandbox — restricted DSL, but still user code.
  • UserBulb — Roslyn-compiled C# = RCE.

Requests for these types receive forbidden-fractal. Workaround: use a CalcGen-generated calculator (e.g., MandelbrotZ2 / Tricorn (Generated)) which is compiled into the EXE at build time and behaves identically to an authored equation.

To loosen this restriction (NOT recommended for any public-facing deployment), edit Server\Guard\FractalTypeAllowlist.cs and rebuild. The default allowlist excludes all three for a reason — accept the risk consciously.


12. Protocol Layer Validators

Two validators run on every request before any render kicks off:

RegionPayloadValidator

Bounds-checks the inbound region payload:

  • centerX / centerY finite (no NaN / Inf)
  • zoom in (1e-30, 1e60)
  • iterations in [64, 4_000_000]
  • Pipe-separated limb format parsed only when quality >= High (DD path)
  • Theme + region names alphanumeric + spaces + dashes only (no path-traversal)

ThemePayloadValidator

Server-supplied themes must:

  • Have ≤ 64 stops
  • Have stop positions in [0, 1]
  • Have RGB values in [0, 255]
  • Be one of Gradient / Cycling / Phong3D / Pbr3D
  • Reject any field exceeding documented limits

Both validators fail fast with a bad-request reply containing a hint string, so clients can diagnose without server logs.


13. Logs + Monitoring

Per-session log files in %APPDATA%\FracturingFog\server-logs\:

server-20260603-141215.log
server-20260603-141215.err

Log lines:

2026-06-03T14:12:15 INFO  listening 0.0.0.0:47823
2026-06-03T14:13:02 INFO  accept 10.0.0.5:54321 thumb=3A7B1C…
2026-06-03T14:13:02 INFO  job ""poster-eagle"" Mandelbrot 7680x4320 q=Ultra
2026-06-03T14:13:48 INFO  job complete 7680x4320 elapsed=46213ms bytes=12.4MB
2026-06-03T14:13:48 INFO  close 10.0.0.5:54321 ok

For a production deployment, tail the log into your log-aggregation pipeline (Elastic / Loki / Splunk). Errors include the offending request hash so you can trace specific clients without storing PII.


14. Status Bar Indicator

The Avalonia MainWindow status bar shows a colored ● Server pill on the right edge:

Color Meaning
Green Local server is up + listening on the configured port
Grey Local server is down
Red Local server reported an error or the management socket is unreachable

Hover for the last error string. Click the pill to open the Server Admin dialog.

Only the local server is reflected — remote server health must be checked on its own host.


15. Troubleshooting

Server starts, status bar stays grey. The status-bar probe is gated to the configured local port. If you changed the port via the admin dialog without restarting, the probe still polls the old port. Restart the UI shell.

Client gets tls handshake failed or chain validation error.

  • Confirm both sides use certs from the same CA.
  • Confirm the server cert SAN includes the hostname / IP the client is dialing.
  • Confirm the system time is in sync (cert validity is time-based).
  • Try revocationCheckMode: ""none"" temporarily to rule out CRL fetch failures.

Client gets forbidden-fractal. The preset targets UserEquation / Sandbox / UserBulb. Pick a built-in family.

Server hits OutOfMemoryException on big posters. Lower queue depth, raise maxMinutes (so the renderer can use disk-spill paths), or schedule big posters during off-peak.

Server log full of accept … thumb=… rate-limited. A client is hammering you. Raise rateLimitPerMinute slightly if it's a legitimate VJ session; lower it (or block at firewall) if it's hostile.

Server log full of bad-request. A client is sending malformed requests — possibly running an older build. Check RegionPayloadValidator / ThemePayloadValidator logs for the specific field that failed.

Server doesn't restart cleanly via the admin dialog. Make sure the local server was spawned BY the admin dialog (Start button). The admin dialog tracks PIDs it started; servers launched from a separate shell are not under its lifecycle control.

Cert revocation online mode hangs at handshake. Your CRL distribution point is unreachable. Switch to offline (uses cached CRLs) or back to none while you fix the upstream issue.


Server Admin Guide · Fracturing Fog · © 2026

Clone this wiki locally