// Technical

How our software works.

For developers and security-minded readers: how each PANMOX product is built, what it does under the hood, and where the limits are. Everything here comes from the source code, and every product links to it. For the plain-words versions, see each product’s own page.

AltNet Relay

The private messenger. Identity, messages, the network, calls, moderation, what we run, and where the limits are. Plain-words version: the AltNet Relay page.

Version 1.0.4Go · Wails v2Windows and Linux from 16 October 2026 · Mac later in October

Identity

  • Each user has an Ed25519 key pair, made on their own computer.
  • Their ID (“username”) is the 64-character hex SHA-256 of the public key.
  • This identity is separate from the computer’s network node key, so it never appears in network routing.
  • An X25519 “box” key for receiving is published in a signed profile record. The record is findable only by someone who already knows the ID; the network can’t be browsed or searched.

Messages

  • Each message is sealed to the recipient with an ephemeral X25519 key exchange and AES-256-GCM.
  • It is signed with Ed25519 and kept in a per-conversation chain: hash-linked, sequence-numbered per direction.
  • Storage addresses are derived by hashing the two IDs (domain-separated), so nothing about a user can be found without their ID.
  • First contact goes through a “doorbell” address. The recipient’s app shows at most the first 3 messages until accepted; this is enforced by the receiver.
  • Text is limited to 16 KiB per message. Data is stored in 64 KiB pieces, sealed before splitting.
Sender app seal: X25519 (eph.) + AES-256-GCM sign: Ed25519 AltNet network Kademlia DHT address = H(domain, ID₁, ID₂) stored sealed, replicated Recipient app verify signature open with box key check chain 1 · store first 2 · watch push (10-min TTL) also delivered directly when both are online Nothing between sender and recipient can open the message.
Figure 1 · A message, from one app to another

Network

  • AltNet is a Kademlia distributed hash table (α = 3) with exact-key lookups only.
  • Values are replicated to the closest nodes, and each node has a storage budget.
  • Connections between live peers use a Noise-XK-style handshake: X25519 + Ed25519 + AES-256-GCM, with forward secrecy.
  • Computers behind home routers are reached through a rendezvous relay that forwards only encrypted bytes.
  • When both people are online, a message is also delivered directly. It is always stored to the network first, so nothing is lost if the app is closed.
  • New messages arrive push-style, through short-lived watch registrations (10-minute TTL), with periodic reconciliation.

Names (@names)

  • @names are unique. They are claimed with an account, and the operator’s server signs a name record with the operator key.
  • Records are valid for 90 days and renewed by the app.
  • The app trusts only the operator’s public key for names.
  • Reserved names (admin, support, panmox, …) and vulgar names are refused.
  • A deleted account’s name is never reissued.

Groups and workspaces

  • Every group message is sealed separately to each member: fan-out, no shared group key.
  • Groups are capped at 32 members, workspaces and channels at 50.
  • Membership comes from admin-owned, numbered snapshots. Nobody is added without accepting.

Calls

  • Calls use WebRTC, with media encrypted by DTLS-SRTP. Call setup (offer and answer) travels as sealed, signed messages in one round trip.
  • Only accepted contacts can ring you, and offers older than 90 seconds never ring.
  • STUN comes from the operator’s server, with Cloudflare’s public STUN as a fallback.
  • When a direct path fails, a TURN relay (coturn, UDP 3478) carries the encrypted media. Credentials are short-lived (1 hour), HMAC-based and given only to signed-in accounts. The relay can’t decrypt calls.
  • Group calls are a full mesh of up to 8 people. During a call, the other person’s computer sees your IP address.
Caller WebRTC Callee accepted contacts only offer / answer as sealed, signed messages · one round trip media, direct: DTLS-SRTP TURN relay · UDP 3478 fallback, still encrypted relay can’t decrypt
Figure 2 · Setting up and carrying a call

Moderation

  • Reports: a report may include up to the last 10 messages of that conversation, decrypted on the reporter’s own computer and sent only if the reporter chooses.
  • Automatic bans: three distinct reporters within 30 days ban an account automatically. Reporter accounts must be at least 72 hours old, and at most 5 different accounts per reporter count in 30 days.
  • Strikes: a reporter whose reports led to bans that were later overturned gets a strike. At 2 strikes their reports no longer count.
  • Ban list: bans are published as an operator-signed ban list on the network, and the person banned is shown a statement of reasons.
  • Workspace reports go, sealed, to the workspace owner only. They are limited to 3 a day, and 1 per person a day.

Accounts and data

  • The account: email and password, held by the AltNet account service, shared with AltNet Studio.
  • Sessions: the app stores only a session token, never the password.
  • Conversations, contacts and keys live on the user’s computer. The only copy that leaves it is the locked copy below, which PANMOX can’t open.
  • Notifications never contain message text.
  • Deleting an account needs an emailed code, the password, the account’s name and a final confirmation. Each step is checked on the server. It removes the account and the server’s record, erases the local data folder, and keeps the @name reserved forever.
  • Signing in on another computer: the app keeps a locked copy of the account on the Relay server: identity keys, contacts, conversations and settings. It is sealed on the user’s computer with AES-256-GCM under a key from PBKDF2-SHA256 (600,000 rounds, random salt), refreshed automatically after changes, and at most 8 MB. Signing in elsewhere downloads and unlocks it with the password. One computer at a time: each install has a random device ID, signing in claims the account, and the previous computer signs itself out. Before sending, the new computer catches up each conversation’s outgoing chain from the network. Users can turn the copy off (it is deleted), or start fresh with new keys and the same @name.
  • Infrastructure: one VPS (Oracle Cloud, Frankfurt) runs the seed node, the Relay server (names, reports, bans), the account service and the call relay. Email is sent through Zoho (EU).
Your computer conversations contacts keys session token, never the password VPS · Oracle Cloud, Frankfurt seed nodeAltNet DHT Relay servernames, reports, bans,locked account copies accountservice call relaySTUN / TURN Zohoemail (EU)
Figure 3 · What runs where

The app

  • Written in Go, with a desktop shell built on Wails v2. The interface runs in the system’s own web engine: WebView2 on Windows, WebKitGTK 4.1 on Linux, WKWebView on macOS.
  • It has no analytics, no third-party scripts and no web fonts.
  • There is a tray icon on Windows. The app starts with the computer through the Run key (Windows), a LaunchAgent (macOS) or XDG autostart (Linux).

Requirements

SystemNeeds
WindowsWindows 10 or 11, x64
Linuxx86-64 with glibc 2.34+ and WebKitGTK 4.1 (Ubuntu 22.04+, Debian 12+)
macOSmacOS 12+ (built locally from the kit, ad-hoc signed)

The numbers, in one place

WhatValue
Messages shown from a stranger before accepting3
Text per message16 KiB
Stored piece size64 KiB
Kademlia lookup parallelismα = 3
Watch registration lifetime10 min
Name record validity90 days
Group size32
Workspace and channel size50
Group call (full mesh)8
Oldest call offer that still rings90 s
TURN credential lifetime1 h
Locked copy: PBKDF2-SHA256 rounds600,000
Locked copy: maximum size8 MB
Computers using an account at once1
Messages a report may include10
Distinct reporters for an automatic ban3 in 30 days
Minimum reporter account age72 h
Accounts one reporter can count against5 per 30 days
Strikes before reports stop counting2
Workspace reports3 a day · 1 per person

Known limits

Said plainly, so you can judge for yourself.

Metadata on a small network
Message contents are always encrypted, but nodes can see IP addresses and which addresses are active. On a small network that picture is richer. Watch registrations can link an IP to the addresses it watches.
Stored messages and key compromise
Stored messages are sealed to a long-lived box key, so someone who later gets that key could open stored messages. Box keys don’t rotate yet.
One computer at a time
An account is in use on one computer at a time (signing in on another moves it there). There is no simultaneous multi-device use yet.
The locked copy relies on the password
A stolen copy can only be opened by guessing the password, which PBKDF2 makes slow but not impossible for a weak one.
No phone apps yet
AltNet Relay runs on Windows, Linux and macOS only.
Unsigned installers
The installers aren’t code-signed yet, and the Mac app is built on the user’s Mac.
Not yet audited
There has been no independent security audit yet.
Operator key
Names and bans depend on the operator’s signing key.

AltNet

The network itself: the node software that every AltNet app runs. It stores and serves .alt sites from the computers of the people who use it. .alt is reserved by the IETF (RFC 9476) for names outside the regular DNS, so AltNet names never collide with the normal internet.

Go · standard library + Go crypto onlyGPL-3.0Source

Identity and transport

  • Every node is an Ed25519 key pair; its 32-byte node ID is derived from the public key.
  • Peer connections use a hand-rolled, Noise-XK-shaped handshake: each side sends its long-term Ed25519 key, a fresh X25519 key and a signature over the session. The responder signs both ephemeral keys, binding its reply to that session.
  • After the handshake every frame is AES-256-GCM, with a separate key per direction and 12-byte counter nonces, so a replayed or reordered frame fails authentication. Keys come from a fresh X25519 exchange per connection, giving forward secrecy.
  • Frames are capped at about 1 MiB; the handshake times out after 10 s; idle connections send a keep-alive every 30 s; a node accepts up to 1,024 connections by default.

Storage and routing

  • A Kademlia distributed hash table: buckets of K = 20, lookups with α = 3 parallel requests, 5 s per request.
  • Files are split into 64 KiB chunks addressed by their SHA-256 hash, so tampering is detectable and identical content is stored once.
  • Each node keeps a persistent on-disk store with a budget (1 GiB by default, at most 64 MiB from any single peer); the oldest entries are evicted first.
  • Maintenance: stored values are republished every hour, peers are checked every 10 minutes, and bootstrap is retried every 30 s with back-off up to 5 minutes.
  • Nodes behind home routers register with a relay so other peers can reach them.

Names, revocation and blocking

  • A name is a signed record pointing name → content root, with a version number that only goes up and a default lifetime of 7 days. Names are at most 253 characters; clocks may differ by up to 5 minutes.
  • Permissioned naming is optional: a node configured with trusted registrar keys resolves only names signed by one of them. Empty by default (first writer wins).
  • Signed revocation: a trusted authority can broadcast a signed dht_revoke that purges a name’s chunks and blocklists them on every node that honours that key. Revocations older than 24 hours, or more than 5 minutes in the future, are rejected.
  • A content blocklist makes nodes refuse to store or serve known-bad hashes.
  • Security of naming and takedowns rests on the authority’s private key, not on keeping the code closed.

Browsing with a normal browser

  • A small DNS resolver answers .alt queries and forwards everything else upstream.
  • An HTTP and HTTPS gateway serves sites by Host header. HTTPS uses a per-install local certificate authority (ECDSA P-256) that is name-constrained to .alt (critical PermittedDNSDomains), so it cannot vouch for any other site. The CA is valid for 10 years; site certificates for 395 days.
  • The resolver and the gateway rate-limit each IP address with a token bucket.
  • An authenticated registrar API publishes content and registers, updates or revokes names; a JSON metrics endpoint reports node status.

AltNet Studio

The desktop app that runs an AltNet node, makes .alt addresses open in any browser, and lets approved accounts publish sites. Plain-words version: the Studio page.

v1.0Go 1.23 · Wails v2 · vanilla JSWindows · LinuxGPL-3.0Source

How it is put together

  • One codebase for Windows and Linux. Operating-system-specific parts live in build-tagged files (for example nrpt_windows.go and nrpt_linux.go); Go compiles only the ones for the target system.
  • Studio starts the altnet node as a supervised child process and talks to it over loopback HTTP: the registrar API, metrics and the gateway.
  • Every install bootstraps from a seed node run by PANMOX (seed.panmox.org), plus any seeds the user adds.
  • The PANMOX naming and revocation keys are built in. Only names the registrar has signed (that is, admin-approved) resolve, and takedowns reach every Studio node.
  • Closing the window hides it; the node keeps running. Studio starts with the computer through the Run key (Windows) or XDG autostart (Linux).

Making .alt work in any browser

  • Windows: an NRPT (Name Resolution Policy Table) rule sends every *.alt query to the node’s resolver on 127.0.0.53:53, which answers 127.0.0.1; the local gateway then serves the site. The rule is installed once through an elevated PowerShell (one UAC prompt) and survives reboots.
  • Linux: 127.0.0.53 belongs to systemd-resolved, so the node’s resolver listens on 127.0.0.1:5354 and Studio adds /etc/systemd/resolved.conf.d/altnet-alt.conf with Domains=~alt, a routing-only domain: only .alt goes there, every other name resolves as before.
  • HTTPS: the “AltNet Local CA” goes into the current user’s Root store on Windows (no admin, this user only) and into the system store via update-ca-certificates on Linux, which WebKitGTK honours.
  • On Windows, optional per-site hosts entries give clean URLs; names are checked against DNS characters before anything is written.

Accounts

  • Accounts and domain requests go to a separate account and registration service (not open source) over HTTPS with a bearer token.
  • The token stays in the Go side of the app and never reaches the user interface; the session is kept in the per-user config folder.
  • The same account is used by AltNet Relay.

Requirements

SystemNeeds
Windowsx86-64
Debian / Ubuntux86-64 · GTK 3 + WebKit2GTK 4.1
Linux needs root
Studio must run as root on Linux: it binds port 80, changes the resolver configuration and installs its CA. It asks through pkexec.
Chrome and Firefox on Linux
They keep their own certificate stores, so they don’t trust the AltNet CA yet. WebKit-based browsers do.
No automatic updates
Version 1.0 doesn’t update itself; new versions are published on panmox.org.

PMX OS

A complete desktop operating system: Debian with a KDE Plasma desktop rebuilt in PANMOX’s look, with AltNet Studio built in. The repository holds the build system. Plain-words version: the PMX OS page.

PMX OS 1Debian 12 · KDE PlasmaBuild code: GPL-3.0Source

How it is built

  • Based on Debian 12 (bookworm), assembled into an ISO with Debian’s live-build inside WSL2 Ubuntu, by numbered scripts: toolchain, scaffold, branding, KDE, apps, installer, rebuild, finalize.
  • A hybrid ISO that boots on UEFI and legacy BIOS. It runs live from USB and installs to disk with a rebranded Calamares installer.
  • Branded end to end: boot splash, Plymouth, SDDM, the GRUB background and the login avatar.
  • Preinstalled: AltNet Studio, PMX Hub (a welcome app), MoxTerminal (GTK 3 + VTE) as the default terminal, and fastfetch. Phosphor mode switches the whole desktop theme between deep cyan and phosphor green.
  • The v1 release is published as two ISO parts (about 1.1 GB and 1.0 GB) with a SHA256SUMS.txt.
  • Debian, the Linux kernel, KDE Plasma, Calamares and the other bundled components keep their own licences, listed in CREDITS.md. The GPL covers the build code; the PANMOX names and branding are trademarks.
Secure Boot must be off
The GRUB EFI binary isn’t signed, so Secure Boot has to be disabled to boot it.
Not a turnkey builder
The build scripts encode PANMOX’s own build environment. They are a faithful record of how PMX OS is made, not a cross-machine build tool.

LinuxSimplify

Two installers from one repository. LinuxSimplify · PMX (v1.0.0) puts PMX OS on a USB stick. LinuxSimplify v0.1 helps people move from Windows to another Linux distribution. Plain-words version: the LinuxSimplify page.

C# · .NET 8Windows: WPF · Linux: Avalonia 11GPL-3.0Source

LinuxSimplify · PMX

  • Finds the newest PMX OS through the GitHub API (repos/panmauk/PMX-OS/releases/latest). Nothing is hard-coded: it works out the ISO parts and the checksum file from the asset names alone.
  • Downloads every part, joins them into one ISO and checks it against the published SHA-256 (or SHA-512, if that is what is published). The ISO is deleted after flashing.
  • Windows: reads the hardware through WMI (Win32_Processor, Win32_PhysicalMemory, Win32_VideoController, Win32_DiskDrive), clears the stick with diskpart clean, locks and dismounts its volumes, and writes the image raw to \\.\PhysicalDriveN. Needs administrator rights.
  • Linux: lists drives with lsblk, unmounts the stick’s partitions, writes with dd bs=4M conv=fsync, then sync and partprobe, elevating through pkexec.
  • Both builds are self-contained single-file executables (Windows x64, Linux x64).

LinuxSimplify v0.1

  • Supports Ubuntu, Lubuntu, Linux Mint, Fedora, Pop!_OS, Zorin OS, Arch Linux, EndeavourOS, Debian and Trisquel.
  • Finds the latest ISO by reading each project’s official release directory or mirror (for example releases.ubuntu.com, the kernel.org Linux Mint mirror, dl.fedoraproject.org), so links don’t go stale.
  • Each distribution has minimum and recommended RAM and disk figures; the scanned hardware gives every distribution a fit score, and the list is sorted by it.
  • Downloads are checked against SHA-256 checksums and written to the stick the same raw way as above.

NeuralXP

A small language model that runs entirely offline on Windows XP-era hardware. Plain-words version: the NeuralXP page.

v1.0.2C++ · Win32Windows XP SP2/SP3 32-bitGPL-3.0Source

Built for old machines

  • A native Win32 program: no .NET and no web engine. Cross-compiled with MinGW-w64 i686 (GCC 10.5, MSVCRT runtime), statically linked, targeting Windows XP (_WIN32_WINNT=0x0501).
  • Compiled for the Pentium M: SSE2 only (-march=pentium-m -mno-sse3, BMI2 off). Newer instructions would crash with “illegal instruction” on real XP hardware.
  • Inference is llama.cpp / ggml, patched for XP: the Vista-only threading primitives (SRWLOCK, CONDITION_VARIABLE) are replaced with CRITICAL_SECTION and Event objects.

The model and each answer

  • The model is Qwen2.5-0.5B-Instruct, quantised to GGUF Q2_K (about 300 MB), and loaded from a local file. A smaller SmolLM-135M model is used if it is present instead.
  • For every answer the window starts llama-simple-chat-headless.exe with a 256-token context, at most 80 new tokens and temperature 0.8, under a fixed system prompt. The previous exchange is passed along as short context.
  • Chats are saved as plain .txt files in a chats folder next to the program.
  • The NeuralXP program contains no networking code; prompts stay on the machine.

Measured

WhatValue
Test machineDell Inspiron 6000 · Pentium M 1.6 GHz · 2 GB
Time for a short answer≈ 30 s
Model file≈ 300 MB

Licences

  • llama.cpp / ggml and cpp-httplib: MIT. Qwen2.5 model: Apache 2.0. GCC runtime: GPL v3 with the runtime exception. Full texts ship with the installer.

LostEngine

A joke search engine: three modes, every answer wrong on purpose. Plain-words version: the LostEngine page.

JavaScriptCloudflare Pages + FunctionsGPL-3.0Source

How it works

  • A static front end (HTML, CSS and plain JavaScript) on Cloudflare Pages, plus one server function, search-stream.
  • Answers stream to the browser as Server-Sent Events, read with fetch and a stream reader, so text appears as it is written.
  • The text comes from Groq’s OpenAI-compatible chat API, model llama-3.1-8b-instant. The API key is a Cloudflare secret, never in the page.
  • Images, videos and links come from DuckDuckGo and Bing image search, with a Google search link as the fallback.

The three modes

  • How it really was: the model writes a confident, encyclopedia-style summary that is false on purpose. Some queries have pinned answers.
  • Searching what you want: the model is asked for the best-known opposite or rival of your query. Real results for that are fetched, then every title and description has the rival’s name swapped for yours (Unicode-normalised, case-insensitive).
  • Searching something: a random word from a fixed list replaces your query; the model writes a short, real summary of that word.
Your query leaves the site
To make the answers, your search text is sent to Groq, and to DuckDuckGo or Bing for results. The front-end code sets no cookies, uses no local storage and has no analytics.

OverByte

Makes files bigger on purpose, while keeping them usable. Plain-words version: the OverByte page.

v1.0C# · .NET 10 · WinFormsWindows x64GPL-3.0Source

Padding that keeps the file valid

  • The original bytes are left intact. The padding goes where each format’s readers skip it, chosen by file extension:
  • PNG: private paDd chunks (16 MiB each, with correct CRCs) before IEND, up to 2.5 GB; anything beyond that as zeros after IEND.
  • JPEG: comment (COM) segments of spaces before EOI, up to 2.5 GB; then zeros after EOI.
  • MP4 / MOV and relatives: an appended free box, which ISO/IEC 14496-12 parsers skip by definition.
  • ZIP-based files (ZIP, DOCX, XLSX, PPTX, ODF, JAR, APK, EPUB, …): padding goes before the end-of-central-directory record, which is moved to the very end where readers look for it.
  • PDF: an incremental update: the padding is a stream object, followed by a new xref and trailer that point back to the original.
  • Everything else: zeros appended to the end (works for WAV, BMP, GIF, FLAC, ISO, EXE and others).
  • Folders: either zipped and padded as one file, or every file padded to a per-file target size.
No undo button
The app has no “restore” function. Because the original data is untouched, the file still opens normally, but removing the padding is up to you.