Wiki tree
Use this as a map. Every node below links to a detailed section.
1) Getting started
Choose what you want to do: operate servers (INS/WebServer) or build a website (Java WebPages + Lua).
1.1 Prerequisites
- OpenSSL (certificate generation)
- For INS: MySQL/MariaDB compatible database
- Download archive (contains SQL + start scripts)
- For FX clients: JavaFX WebView (WebEngine DOM) no JavaScript
1.2 Downloads & start scripts
The download archive includes .sh (Linux) and .bat (Windows) scripts for execution.
2) Server setup
Server setup is split into a global TLS section and per-server setup (INS, WebServer).
2.1 Certificates (Root-CA + Server)
Certificates are required for secure communication in OAC. You generate a Root-CA and then generate server certificates based on it.
*.key files private. Distribute only Root-CA *.pem to clients.
2.1.1 Folder layout
certificates/
ca/ # Root-CA (.pem) must exist on server AND client
key/ # Server private key (.key)
server/ # Server certificate (.crt)
2.2 INS Server
INS requires a database, INS-specific certificate naming, and an INS config.properties.
The download contains the SQL file and start scripts (.sh/.bat).
2.2.1 Database
Import the SQL file from the download into your DB. Then configure DB credentials via config.properties.
2.2.2 INS certificates (naming rules)
Create Root-CA (INS)
openssl genrsa -out myCA.key 4096
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 3650 -out myCA.pem
myCA.key = private Key for CA (keep secret)
myCA.pem = public Root-Certificate for signing server and client certificates
Required filenames: ca_ins_[public ip].[extension]
# Example for public IP 203.0.113.10
ca_ins_203.0.113.10.key
ca_ins_203.0.113.10.pem
Create Server Certificate based on Root-CA (INS)
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out server.crt -days 825 -sha256
server.key = private Key for Server
server.crt = Server-Certificate signed by Root-CA
Required filenames: cert_ins_[public ip].[extension]
# Example for public IP 203.0.113.10
cert_ins_203.0.113.10.key
cert_ins_203.0.113.10.crt
Root-CA →
certificates/caServer key →
certificates/keyServer cert →
certificates/server
2.2.3 config.properties
Generated on first run. Fill it like this:
db.password=DB PASSWORT
db.url=jdbc:mysql://localhost:3306/DATABASE?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
db.user=USER
ins.frontend=INS FRONTEND SITE (HOST) # Erreichbar über register.oac
ins.info=INS INFO SITE (HOST) # Erreichbar über info.oac
port.tcp=1026
port.udp=1025
2.3 WebServer
WebServer uses a config.properties and access control via rules.ini + auth.ini.
2.3.1 config.properties
#Sun Jan 18 21:55:38 UTC 2026
maxuploadmb=1024 # max upload in mb
port.tcp=1028
port.udp=1027
sessionexpiremin=1000 #session expiration in min
2.3.2 rules.ini (allow/deny/auth)
{
"allow": [
"index.html",
"css/*",
"private/info.php"
],
"deny": [
"private/*"
],
"auth": [
"private/*",
"admin/*"
]
}
2.3.3 auth.ini (users/hashes)
admin:5e884898da28047151d0e56f8dc6292773603d0d6aabbddab8f91d8e5f99f6c7
user:e99a18c428cb38d5f260853678922e03abd8335f
3) Website development
Websites are built with Java WebPages (server-side rendering) and Lua (client-side behavior).
3.1 Java WebPages
Every page implements WebPage and is mapped via @Route(path="/...").
The handler receives WebPageContext (client, request, session, params, hasher).
3.1.1 Routing (@Route)
@Retention(RUNTIME)
@Target(TYPE)
public @interface Route {
String path(); // must start with '/'
}
3.1.2 WebPageContext
Context fields:
client(ConnectedWebClient)request(WebRequestPacket)session(SessionContext)params(RequestParams)hasher(WebHasher)
3.1.3 RequestParams
Reads parameters from request headers (case-insensitive) and can hash values:
String user = ctx.params.getTrimmed("user");
String sha = ctx.params.getSha256Hex(ctx.hasher, "user");
3.1.4 SessionContext
if (ctx.session.isValid()) {
String user = ctx.session.getUser();
String sessionId = ctx.session.getSessionId();
}
3.1.5 Html helpers
String body = "<h1>" + Html.esc("Hello") + "</h1>";
String html = Html.page("Title", body);
byte[] bytes = Html.utf8(html);
3.1.6 HttpsProxy
WebResponsePacket resp = HttpsProxy.proxyGet(ctx, "https://example.com/");
3.1.7 ContentTypeResolver
String ct = ContentTypeResolver.resolve("index.html"); // text/html
boolean img = ContentTypeResolver.isImage("logo.png");
Files like .js, .ts, .php, .py, .java are served as text/plain.
3.2 LuaScript (FX / no JavaScript / no jsoup)
The client executes Lua from standard HTML <script> tags.
JavaScript is disabled and is never evaluated.
<script> as Lua.
You do not need type="lua". The previous type-based detection is replaced.
<script> blocks, they will not run and may break behavior.
Use Lua for client logic.
3.2.1 Script tags & bootstrap
Two forms are supported:
- Inline: Lua code is read from the script element text content.
- External: Lua is loaded via
srcusing the clientResourceHost.
<!-- Inline Lua -->
<script>
console.log.info("hello from lua")
</script>
<!-- External Lua (loaded by the client via ResourceHost) -->
<script src="/scripts/app.lua"></script>
src by itself (no JavaScript, no browser fetch logic).
You control how/where scripts are allowed to load in your ResourceHost.
3.2.2 DOM access (dom.*)
DOM access is backed by the JavaFX WebView DOM (WebEngine.getDocument() / W3C DOM).
jsoup is not used.
- Element identity is the HTML attribute
id. - Missing ids are auto-assigned (
__auto_*) so every element is addressable. - Query helpers: by tag / by class, parent/children traversal, attributes and text content.
innerHTML/classList/computed styles are not standard W3C DOM APIs.
Use ui.* helpers for common UI mutations.
3.2.3 Events (on:* + events.*)
Auto-binding via DOM attributes:
<button id="saveBtn" on:click="handlers.save">Save</button>
<script>
handlers = {}
function handlers.save(e)
console.log.info("clicked: " .. e.target)
end
</script>
Manual binding via API:
<script>
handlers = {}
events.on("saveBtn", "click", "handlers.save")
events.onGlobal("ready", "handlers.ready")
</script>
e with
e.target, e.type and e.data.
3.2.4 UI (ui.*)
<script>
ui.alert("Hello OAC")
ui.setText("title", "Updated title")
ui.addClass("box", "active")
ui.setStyle("box", "opacity", "0.9")
</script>
3.2.5 Security policy
Default UI policy:
- timeout: 50ms
- instructionLimit: 200_000
- hookStep: 5_000
os, io, debug, luajava,
and module loading (package/require/loadfile/dofile) in production clients.
3.2.6 FX notes (threading & limitations)
- Threading: DOM reads/writes must happen on the JavaFX Application Thread.
- Lua execution: Lua runs guarded on a dedicated thread (timeout + instruction budget).
- Bridging: Event callbacks must forward into Lua via the router (host → LuaEventRouter).
- No JS: do not rely on browser JS features (fetch, DOM APIs exposed only to JS, etc.).
ui.* and dom.*,
not through JavaScript attributes or JS libraries.
4) Conventions & INS
OAC relies on consistent hostnames and dedicated pages for discovery and trust.
4.1 Info pages (info.<tld>)
For every website operator: each InfoName needs an info page reachable via info.<top level name>.
example, the info page must be available at info.example.
5) FAQ
Why is JavaScript not executed?
OAC does not execute JS. Client-side behavior is implemented in Lua only.
Do I need type="lua" for scripts?
No. The FX client executes Lua from standard <script> tags. Use src for external Lua files.
Why was jsoup removed?
DOM access is now backed by JavaFX WebView DOM (W3C DOM). This removes the need for jsoup and avoids parsing mismatches.
What breaks TLS setup most often?
Wrong filenames or wrong folder placement. Follow the naming formats exactly.
Do I need an info page for my InfoName?
Yes. Each InfoName should expose an info page reachable via info.<top level name>.