TempleOS
Unofficial mirror of God's chosen operating system.
Public domain.
Enterprise Edition additions
What was added (all under TempleOSCD/):
- Version
5.1 EE(sys_os_version=5.100,DD_OS_NAME_VERSION= "TempleOS V5.1 EE"). Terry stopped at 5.03; the console header, the boot banner, the HtServServer:header and the WgetUser-Agentall say 5.1 EE now -
Adam/Net/- Ethernet, ARP, IPv4, ICMP, UDP, TCP, DHCP, DNS, HTTP client, BSD-style sockets -
Adam/HwSupp/- PCI helpers and NIC drivers: AMD PCnet-PCI II, Intel e1000 (82540EM), virtio-net (legacy). One card was a sin, three is a habit -
Adam/MakeAdam.HC- loads the stack at boot (#include "Net/MakeNet") -
Once.HC- runsNetcfg(DHCP) at startup when a NIC is found -
Apps/Wget.HC- download a URL -
Apps/HtServ.HC- HTTP server, serves::/Www(Www/Index.HTMis its default page) -
Adam/Net/Confessional.HC- remote HolyC console on port 23 (see below) -
Adam/Net/DnsOracle.HC- DNS server on UDP 53 that answersTXTwith a Bible verse (see below) -
Adam/Net/Mcp.HC- MCP server on HtServ'sPOST /mcp: the oracle and God's words for AI agents (see below) -
Demo/Network/- TCP/UDP echo client/server demos -
Misc/Pal*.HC- extra color palettes (ConEmu, Monokai, Ubuntu),#include "::/Misc/PalMonokai"; the choice survives a reboot,#include "::/Misc/PalStd"gives Terry's colors back -
Adam/Crypto/- SHA-256, HMAC, HKDF, BLAKE2s (with HMAC-BLAKE2s and the WireGuard KDF), ChaCha20-Poly1305, XChaCha20-Poly1305 and X25519 in plain HolyC, compiled into Adam;#include "::/Adam/Crypto/CryptoTest"checks them against the RFC test vectors -
Adam/Crypto/CrRand.HC- the Holy Spirit's random numbers for keys: network IRQs, keyboard, timer jitter, RDRAND and~/RandSeed.BINpoured through BLAKE2s into a ChaCha20 generator.X25519KeyGen,CrRandBytes,CrGodWords(a key fingerprint in God's words).GodWordno longer hangs on a VDS waiting for a hand to press OKAY -
Adam/Crypto/WgNoise.HC- WireGuard's handshake, Noise_IKpsk2 from the whitepaper:WgInitCreate/WgInitConsume,WgRespCreate/WgRespConsume, TAI64N, replay and forgery checks.WgData.HCseals the data packets, with Linux's three keypair slots and a 2048 replay window.tools/wg_vectors.pyis the second witness, the same handshake in Python that CryptoTest checks against -
Adam/Net/Wg.HC- WireGuard on the wire, UDP 51820:WgEnable(comes up at every boot from~/Wg.HC),WgPeerSet,WgPeerDel,WgSave,WgPing,WgRep(likewg show),WgDown. Keys in base64 likewg, the official apps connect. Keepalives, rekey every two minutes, cryptokey routing, cookies andmac2under load (XChaCha20-Poly1305 for them). See WireGuard. The tunnel is a second interface: TCP and UDP both ways, HtServ and the Confessional answer at the tunnel address.tools/wg_interop.pychecks it against Linux's kernel WireGuard in a container, both knocking first, ping both ways, cookies both ways, rekey.WgAwgNew/WgAwgput on AmneziaWG's disguise (junk, padding, own message types) for countries whose DPI strangles WireGuard;tools/awg_interop.pychecks it against amneziawg-go -
Adam/Net/IPv4.HC- the Word on the wire: every small packet the Temple sends carries the next two letters of the King James Bible in its IP Identification field, with Don't Fragment.tools/wire_scripture.pyreads them back from a pcap (see below) -
snail.py- host side of the Snail serial tunnel
Building and running
TempleOS can only be compiled by TempleOS, so the build boots a stock TempleOS
live CD in QEMU, attaches a FAT32 disk with TempleOSCD/ and runs
tools/MakeISO.HC there (kernel compile + RedSeaISO).
brew install qemu mtools # Debian: apt install qemu-system-x86 mtools
tools/build_iso.py [path/to/TempleOS.ISO] # default: ../templeos/TempleOS.ISO
tools/run_mac.sh # boots out/TempleOSEE.ISO with a PCnet NIC
Like the official distro, files are stored compressed (.Z) in the ISO; some
TempleOS code looks for the .Z names explicitly (FileFind(BIBLE_FILENAME)),
and with uncompressed files e.g. Bible passages came out empty.
The build takes about 3 minutes. It types commands into the VM on a timer,
so on a slow machine raise BOOT_WAIT and STEP_SCALE (env vars). Screenshots of
every step go to out/screens/.
CI (.gitlab-ci.yml) does the same on a shared runner. The runner has no internet,
so the tools come from our image (tools/ci/Dockerfile, pushed to the project's
Container Registry) and the stock ISO from the project's Package Registry
(templeos-base/5.03/TempleOS.ISO, SHA-256 checked). TempleOSEE.ISO and the
screenshots are published as artifacts.
Hard disk for hosting without IDE
Terry installed TempleOS on IDE. Two cables, a jumper, master and slave, you could see where your bytes went. The hosting company has no IDE. It has a SCSI controller that is really the host pretending, and the host answers to whoever owns the rack.
So the kernel now speaks virtio-scsi (Kernel/BlkDev/DskVirtioScsi.HC, legacy I/O
ports, 1AF4:1004, polled). It has to live in the kernel: Adam and the Compiler are
loaded from that disk. To the rest of TempleOS it is an ATA drive with
BDF_VIRTIO_SCSI set, because letters C-L are ATA and that is carved in stone.
DskPrt, Fmt, BootHDIns and the MBR walk never know. At boot VSMountAuto mounts the
first virtio-scsi disk at C.
tools/build_iso.py ~/templeos-base/TempleOS.ISO
tools/build_hdd.py --size 2G --vmdk --test # out/TempleOSEE.img and .vmdk
build_hdd.py boots the ISO with a blank disk on virtio-scsi and confesses the
install over the Confessional: DskPrt C and D, copy the Temple to both, BootHDIns
compiles a kernel for each, BootMHDIns writes the MBR. --test then boots from
the disk alone, writes a file, reboots and checks it persists.
The MBR menu used to wait for a key forever. Nobody sits at a rented server, it would wait until Judgement Day. Now it takes the first TempleOS drive after about five seconds.
Proxmox-style hosting: SCSI controller VirtIO SCSI or VirtIO SCSI single, machine i440fx, NIC VirtIO or E1000. LSI 53C895A, PVSCSI and MegaRAID are not supported. Neither is q35, it has no IDE for the CD either.
Updating a running Temple
The hosting company will not swap a disk image, and a new VDS means a new IP. So the Temple is updated in place, delivered by hand over the Confessional like Moses carried the tablets:
tools/update_vds.py 195.28.181.151 --ref b5a3276 # first time: the commit the image was built from
tools/update_vds.py 195.28.181.151 # after that it reads C:/Home/Deployed.TXT
It diffs TempleOSCD/ between the commit the machine runs and your working tree,
pushes every changed file through a one-line hex decoder (files that are .Z on
the disk stay .Z), recompiles the kernel with BootHDIns('C') if Kernel/ or
Compiler/ changed, writes the new commit to Deployed.TXT and reboots.
--dry-run shows what it would do, --no-reboot leaves the reboot to you.
Only C: is touched. D: keeps the old Temple: if C: does not come back, pick D at the boot menu in the VNC console.
The Confessional has no password. Open port 23 in the hosting firewall to your own IP only, and only while you update. The CIA has an IP too.
Running with networking
God said TempleOS has no networking. Terry kept the Temple offline so the CIA could not crawl in through the wire. We sinned once with PCnet. Then we sinned twice more. The Temple now speaks to three cards, first one found wins:
- AMD PCnet-PCI II (
1022:2000) - the original sin - Intel e1000 82540EM (
8086:100E) - every hypervisor has one. Intel also has the Management Engine. We wrote the driver anyway. Repent - virtio-net (
1AF4:1000, legacy I/O ports) - the card that admits it is the host pretending. The hypervisor reads every byte. It always did
None of them may interrupt. The rings are polled from the timer, like PCnet was all along. Polling is honest.
QEMU: -netdev user,id=u1 -device pcnet,netdev=u1 (or e1000, virtio-net-pci);
NIC=e1000 tools/run_mac.sh picks your sin. VirtualBox: PCnet-PCI II,
Intel PRO/1000 MT Desktop or virtio-net, attached to NAT.
No DHCP at your hosting company? It writes your address in a web panel and expects cloud-init to read it. TempleOS does not do cloud-init, the cloud is where the CIA keeps your files. Type your address at the VNC console:
NetcfgStatic("185.241.6.18","255.255.255.0","185.241.6.1","8.8.8.8"); // now, until reboot
NetcfgSave("185.241.6.18","255.255.255.0","185.241.6.1","8.8.8.8"); // now, and every boot
Either can be called again at any time to move the machine. Open connections die,
servers on INADDR_ANY (HtServ, the Confessional) keep listening on the new address.
NetcfgSave writes ~/NetCfg.HC, Once.HC runs it instead of DHCP, Del("~/NetCfg.HC")
goes back to DHCP. Keep the address out of the image, whoever downloads the image
should not learn where your Temple lives. If you must, tools/build_hdd.py --ip ... --gw ... bakes it in.
After boot:
Netcfg; // DHCP (Once.HC runs NetcfgAuto: ~/NetCfg.HC or DHCP)
#include "::/Apps/Wget"
Wget("http://example.com/");
Host("templeos.org"); // DNS lookup
The Word on the wire
Every packet the Temple makes that is 576 bytes or less, which is every TCP segment, every ping and every DNS question, leaves with Don't Fragment and the next two letters of the King James Bible in its 16-bit Identification field. The packets read Genesis to Revelation, one pair each, 4 million letters, then start again. Nobody asked. The CIA reads your packets anyway, now they read Scripture.
$ tcpdump -nn -v -X host 10.0.2.15
IP (tos 0x0, ttl 64, id 27745, offset 0, flags [DF], proto TCP (6), length 40)
0x0000: 4500 0028 6c61 4000 4006 b65e 0a00 020f E..(la@.@..^....
IP (tos 0x0, ttl 64, id 28260, offset 0, flags [DF], proto TCP (6), length 40)
0x0000: 4500 0028 6e64 4000 4006 b45b 0a00 020f E..(nd@.@..[....
la, nd: "let the dry land appear", Genesis 1:9. tcpdump prints a space
as a dot. To read it in a row:
tools/wire_scripture.py wire.pcap 10.0.2.15
One line per receiver, each from In the beginning.
It is safe. RFC 6864: the ID of an atomic datagram, DF and not a fragment, is used by nobody, nothing reassembles it. A packet over 576 bytes, a big WireGuard datagram or a friend's packet out through the NAT, may be cut on the way. Those get no DF and a plain counter in the ID, because the ID is what glues the pieces back together and Scripture repeats itself. Packets that WgForward passes from friend to friend keep their own ID, a router does not touch it.
Every host hears its own reading. The first packet to a new address starts at "In the beginning", and nobody misses a letter because the Temple was talking to somebody else. A friend in the WireGuard tunnel reads one Bible in the packets inside it and another in the datagrams around them. The Temple remembers 128 hosts; the one silent longest makes room for a new one, and if he comes back he starts at Genesis again. He missed the service.
Until the whole Bible is read from ::/Misc/Bible.TXT.Z, a moment after boot, the
wire preaches Genesis 1:1 from memory.
IPv4Scripture; // who is reading where
IPv4ScriptureReset("1.2.3.4"); // he starts again at In the beginning
IPv4ScriptureReset; // everybody does
IPv4Scripture(OFF); // no DF, a plain counter, until reboot
IPv4: the wire preaches, 4139838 letters from Genesis to Revelation
10.0.2.2 280 it was good: and God divided the light from the...
132.66.8.3 8 eginning God created the heaven and the earth. A...
Time from Jerusalem (Ntp)
At boot, after the network, the Temple asks Israeli NTP servers what time it is,
nearest to Jerusalem first: ntp.ac.il (National Physical Laboratory, the atomic
clocks of Israel Standard Time), ntp.huji.ac.il (Hebrew University), then Tel Aviv,
Petah Tikva, Haifa, then the Israeli pool. The first one that answers wins.
NtpDaemon asks again every 6 hours.
The answer is never written to the CMOS. It goes to sys_clock_adj, which Now()
adds to the RTC, in RAM only. A wrong or spoofed answer dies with the next reboot
instead of being burned into the clock.
Ntp; // ask now
NtpRep; // who answered, how far off the RTC is
sys_clock_adj=0; // trust the bare RTC again
Now() is UTC, as Terry meant it; the screen adds local_time_offset
(~/HomeLocalize.HC). Good to the second, the RTC knows no less.
DNS oracle
Ask God from any terminal on Earth:
$ dig +short TXT oracle.temple.example.com
"Zechariah 11:12 And I said unto them, If ye think good, give me my price; and if not, forbear. So they weighed for my price thirty pieces of silver."
The Temple answers DNS on UDP port 53, Adam/Net/DnsOracle.HC. No TCP, no HTTP,
no TLS. One question in, one verse out, like the Urim and Thummim. Every resolver
on the planet carries the Word to whoever asks, and caches nothing: the TTL is 0,
ask again and God answers again.
The verse is picked the way GodBiblePassage picks it, from the timer. Terry let
the Holy Spirit speak through the moment of your keystroke; here it speaks through
the moment your question arrives at the Temple. Name a verse and you get that one:
dig +short TXT john.3.16.oracle.temple.example.com
dig +short TXT 1.kings.8.27.oracle.temple.example.com # or 1kings.8.27
dig +short TXT songofsongs.2.1.oracle.temple.example.com # book name, spaces dropped
A book God does not know, or a verse that is not there, and He answers what He
wants. Any name with an oracle label is the oracle, whatever zone is above it.
A and other types get an empty answer, names without oracle get REFUSED: we
are not a resolver.
Start it at the TempleOS command line:
DnsOracle; // open it now
DnsOracleRep; // how many asked, who asked last and what they were given
DnsOracleEnable; // open it at every boot (~/DnsOracle.HC, like HtServ)
DnsOracleDisable; // and stop doing that
Off by default, a Temple keeps port 53 shut until its keeper says otherwise.
To let the world ask, delegate a subdomain to the Temple at your DNS provider.
Point the NS at a name outside the delegated zone, the Temple only answers for
the oracle and refuses to say who its own name server is:
temple IN NS templeos.example.com.
templeos IN A 195.28.181.151
Open UDP 53 in the hosting firewall. Then dig TXT oracle.temple.example.com from
anywhere. Locally: -netdev user,...,hostfwd=udp:127.0.0.1:5300-:53 and
dig @127.0.0.1 -p 5300 TXT oracle.x.
Plain DNS, 512 bytes, no EDNS, no TCP fallback. Esther 8:9 does not fit, the king's
scribes wrote too much: it ends in .... The KJV in the Temple has 31102 verses,
the oracle knows all of them.
MCP (the machines ask God)
The machines of the age want to talk to God too. HtServ answers the Model Context
Protocol on POST /mcp, written in HolyC, Adam/Net/Mcp.HC. Two tools:
-
oracle- one verse of the KJV, picked by the Holy Spirit from the moment the question arrives, or the verse you name (ref:"John 3:16","1 Kings 8:27") -
god_words- words from Terry's God vocabulary, like F7 in the Temple (count: 1 to 64, default 10)
Give it to Claude Code:
claude mcp add --transport http temple http://temple.pushamp.com/mcp
Then ask Claude to consult the oracle.
Locally (tools/run_mac.sh) it is http://localhost:8686/mcp, with one catch. QEMU's
user networking resets the second of two connections opened in the same millisecond,
it never even reaches the Temple, and MCP clients open a GET and a POST at once. Real
networks do not do that, the server on the internet takes both. Test against the
server, or put a forwarding proxy in front of QEMU.
HtServ must be running, the tools live behind its door (HtServEnable;). The oracle
does not have to be open on port 53, the Bible is read into memory on the first
question.
Streamable HTTP without the stream: one JSON-RPC message in, one JSON answer out,
Connection: close. GET /mcp is 405, God has no news feed. No sessions, no
batches, no password, no Origin check: both tools only read, and what they read is
public domain since 1611. The JSON parser is fifty lines of HolyC, a JSON library is
how the committees get in.
No HTTPS, so claude.ai custom connectors, which only talk TLS, cannot come in. Claude Code can.
WireGuard (a tunnel to your phone)
The Temple speaks WireGuard, written from the whitepaper in HolyC:
Adam/Crypto/WgNoise.HC does the handshake, WgData.HC the packets,
Adam/Net/Wg.HC the wire. The CIA sees UDP noise. The official WireGuard apps
for Android, iOS, macOS and Windows connect to it, and so does Linux's wg.
The tunnel is the stack's second interface. A friend reaches everything the Temple
serves at its tunnel address: http://10.66.66.1 is HtServ, 10.66.66.1:23 the
Confessional, ping answers too. And the Temple reaches its friends: anything it
sends to an address in a friend's allowed IPs goes into the tunnel, create_connection,
Wget and the rest do not know.
1. On the Temple. Once, at the VNC console or over the Confessional:
WgEnable; // a new key, UDP 51820, 10.66.66.1/24, and ~/Wg.HC
It prints the Temple's public key. You give that key to your friends. The private
key never leaves the Temple. Another address or port: WgEnable("10.8.0.1/24",51821);.
2. In the hosting panel. Open UDP 51820.
3. On the phone. In the WireGuard app: +, then Create from scratch:
[Interface]
PrivateKey = (press Generate)
Address = 10.66.66.2/32
[Peer]
PublicKey = <the Temple's public key>
Endpoint = 195.28.181.151:51820
AllowedIPs = 10.66.66.1/32
PersistentKeepalive = 25
The app shows its own public key under the private one. That is the one the Temple needs. The private one stays on the phone.
4. Back on the Temple. Let the phone in, and save:
WgPeerSet("<the phone's public key>","10.66.66.2/32");
WgSave;
Switch the tunnel on in the app, Latest handshake appears, 10.66.66.1
answers ping (any ping app) and http://10.66.66.1 opens HtServ in the phone's
browser, if HtServ runs. On the Temple, WgRep; shows the phone, the address
it came from, the handshake and the bytes.
Where a box at the border knows WireGuard (AmneziaWG). In Russia, and not only there, the provider's DPI recognizes the WireGuard handshake and lets a dozen packets through, then strangles the flow. The handshake succeeds, ping works, a web page never loads. The cure is AmneziaWG: the same crypto, but junk datagrams before each knock, random bytes in front of each message, and other numbers where WireGuard puts 1 2 3 4. On the Temple:
WgAwgNew; // makes up a disguise, puts it on, prints it
WgSave;
On the phone use the AmneziaWG app (or AmneziaVPN, add a config) instead of
WireGuard, with the same config as above plus the lines WgAwgNew printed, in
[Interface]:
Jc = 7
Jmin = 47
Jmax = 87
S1 = 73
S2 = 124
S3 = 0
S4 = 0
H1 = 751269707
H2 = 1053597467
H3 = 796418437
H4 = 218630709
Every friend uses the same S1 to S4 and H1 to H4 as the Temple; Jc, Jmin and Jmax
are only for whoever knocks. A disguise from someone else's config goes in as it is:
WgAwg("Jc=4 Jmin=40 Jmax=70 S1=52 S2=110 H1=... H2=... H3=... H4=...");, ranges
like H1=100000-199999 work too. WgAwg; goes back to plain WireGuard, and then
the plain WireGuard apps connect again. I1 to I5 are not done; leave them out.
tools/awg_interop.py checks the Temple against amneziawg-go, the engine of the
Amnezia apps, built from source in a container.
More friends. Each one gets its own key and its own address in the tunnel:
WgPeerSet("<his key>","10.66.66.3/32"); // he knocks first
WgPeerSet("<his key>","10.66.66.4/32","203.0.113.7:51820",25); // we knock, keep alive
WgPeerSet("<his key>","10.66.66.5/32",NULL,0,"<preshared key>"); // psk, like wg genpsk
WgPeerDel("<his key>"); // forget him
WgSave; // make it last
The same key twice changes that friend, it does not add another. Allowed IPs may be
several, "10.66.66.6/32,10.1.0.0/16". Endpoints are addresses, not names. Sixteen
friends at most.
At boot. ~/Wg.HC is plain HolyC, WgUp(...) and one WgPeerSet(...) per
friend. Once.HC runs it after the network and the clock: a handshake carries the
time, and a friend refuses a Temple that knocks from the past. WgSave; writes it
again, WgDisable; deletes it. WgEnable; with a saved file keeps the saved key,
a new one would orphan every friend who knows the old one.
The private key is in that file. Whoever reads it is the Temple, as far as your friends can tell. Keep port 23 shut, the Confessional can read any file.
The Confessional only through the tunnel. Close TCP 23 in the hosting panel and
leave UDP 51820 open. The Temple still listens on 23, but only friends with a key
get to it, at 10.66.66.1:23:
CONFESS_HOST=10.66.66.1 CONFESS_PORT=23 tools/confess.py 'WgRep;'
tools/update_vds.py 10.66.66.1
with the tunnel up on your computer (the WireGuard app, AllowedIPs = 10.66.66.1/32).
The rest:
WgRep; // like wg show
WgPing("10.66.66.2"); // ping a friend through the tunnel
WgGenKey; // a key pair, for a friend without an app to make one
WgDown; // close the tunnel until WgUp, or the next boot
Under a flood. More than ten knocks in a second and the Temple is under load:
a knock without a good mac2 gets a cookie back instead of the Curve25519 work,
as the paper says. A real friend comes back five seconds later with the cookie and
gets in; a flooder with forged addresses never sees his cookies. Cookies from a
friend under load are taken too. WgCookieAlways; asks for a cookie on every knock,
for the paranoid; WgRep; counts them.
Friend to friend. WgForward; makes the Temple the hub: a phone at 10.66.66.2
reaches a laptop at 10.66.66.3 through it, the way ip_forward does it on Linux.
Each packet loses one hop of TTL and is sealed again with the other friend's keys.
Only between friends: nothing goes out to the internet, the Temple does no NAT.
Each friend must send the whole tunnel to the Temple, AllowedIPs = 10.66.66.0/24
on his side, or his own app keeps the packet for the other friend at home. Off by
default, because a friend's key should open the Temple, not every other friend.
WgSave; keeps it, WgForward(OFF); turns it off, WgRep; counts what passed.
Out to the internet. WgNat; makes the Temple a home router for its friends: a
packet for no friend leaves through the card with the Temple's address and a port
of its own, 20000 to 21023, and the answer to that port goes back to the friend it
belongs to. TCP, UDP and ping. On the friend's side send everything into the tunnel
and pick a DNS server out there:
AllowedIPs = 0.0.0.0/0
DNS = 1.1.1.1
A conversation is forgotten after 10 idle minutes for TCP, 30 seconds after its FIN,
3 minutes for UDP and 30 seconds for ping, the way Linux's conntrack does it, only
much shorter: a phone opens hundreds of connections and forgets them, and there are
1024 ports. A packet coming home that is too big for the tunnel is cut in IP fragments.
WgSave; keeps it, WgNat(OFF); turns it off, WgRep; counts it.
Nothing goes through and WgRep; says "from an address the key may not use"? The
friend's app has the wrong Address =, it must be one of the allowed IPs the Temple
gave his key. WireGuard drops such packets in silence, the Temple at least tells you. The Temple's
public address is now the address of everything its friends do. Choose your friends
like God chose Israel.
Not done yet: IPv6, names for endpoints. A UDP socket keeps 16 datagrams while the Temple is busy, a bigger burst loses the rest; TCP sends them again. TCP's segments are 536 bytes, well inside the tunnel's 1420.
Locally tools/run_mac.sh forwards the Temple's UDP 51820 to 127.0.0.1:51830.
tools/wg_interop.py checks the Temple against Linux's kernel WireGuard in a
container: both sides knock first, ping goes both ways, Linux opens the
Confessional through the tunnel and the Temple connects out to Linux, a second
Linux pings and talks TCP to the first through the Temple with WgForward;, Linux goes
out through the Temple's WgNat; for ping, DNS, a megabyte over HTTP and Cloudflare's
1.1.1.1, and with
--rekey the keys are rotated after two minutes.
Confessional (remote HolyC console)
Adam/Net/Confessional.HC starts with the network stack and listens on port 23
(telnet-compatible). Each line you send is compiled and run like on the command line,
and everything it prints comes back as plain text (DolDoc colors stripped).
tools/run_mac.sh forwards it to 127.0.0.1:2323:
tools/confess.py 'DrvRep;' 'Dir("::/Apps");' # run and print output
echo 'Wget("http://ifconfig.me/ip");' | tools/confess.py
tools/confess.py -i # interactive
nc 127.0.0.1 2323 # raw; 'amen' to leave
The oracle works remotely too: the arrival time of every byte you send feeds the Holy Spirit (like the keystroke time does for F7), so no timer pop-up appears:
tools/confess.py 'GodWord;GodWord;GodWord;' 'GodBiblePassage(5);' 'BibleVerse(,"John,3:16",3);'
GodSong and GodDoodle still need the VM keyboard/mouse.
One line = one statement (no multi-line functions). Each connection is its own task,
so variables live until you disconnect. Anything waiting for the VM keyboard
(GetChar, pop-ups) will block the session. There is no authentication: with QEMU user
networking only the forwarded host port can reach it, but in bridged mode anyone
on the LAN can run code in the VM.
The web server has its own section below.
Web server (HtServ)
Terry built a Temple. We put a web server in it. The CIA can now read the Temple over HTTP, and so can you.
Before you start
-
Network. The machine needs an address. With DHCP it gets one at boot. Without DHCP (most VPS hosting), type yours once at the VNC console:
NetcfgSave("195.28.181.151","255.255.255.0","195.28.181.1","8.8.8.8");It applies at once and every boot after. Check it with
Host("ya.ru");, an address should come back. Details in Running with networking. -
Firewall. Open port 80 in your hosting panel. Keep port 23 (the Confessional) closed, open it only to your own IP and only while you run
tools/update_vds.py.
Start
At the TempleOS command line, case matters (HtServ, not Htserv):
#include "::/Apps/HtServ"
HtServ;
It prints Serving /Www on port 80 and holds that terminal. To keep your terminal,
give the server one of its own:
XTalk(User,"#include \"::/Apps/HtServ\"\nHtServ;\n");
Open http://<your IP>/. Locally, tools/run_mac.sh forwards the VM's port 80 to
http://localhost:8686/ (HTTP_PORT=... to change it).
Start at boot
Off by default. A Temple keeps its doors shut until its keeper says otherwise.
HtServEnable; // from the next boot on, HtServ starts by itself
HtServDisable; // and stops doing that
It is just a file, ~/HtServ.HC. If it is there, Once.HC runs it after the network
is up and then starts HtServ in a task with no window, HtServ; in TaskRep;. Both
of Terry's consoles stay yours. Any HolyC in it runs first, so
to boot with the chatter on, uncomment htserv_verbose=TRUE; in it
(Ed("~/HtServ.HC");).
Stop
Started at boot: HtServStop;. Started by hand: click the server's window and press
Ctrl+Alt+C. Sessions still sending finish or time out on their own. Run HtServ;
again to start over.
Pages
Everything under ::/Www is served as is. / means /Www/Index.HTM. A missing file
is a 404.
.HTM files may carry HolyC between <exe> and </exe>. It runs on every request,
and whatever it passes to StreamPrint goes into the page at that spot:
<p>The Temple says: <exe>if (god.num_words) StreamPrint("%s",god.words[RandU32%god.num_words]);</exe></p>
Do not call anything that waits for the keyboard (GetChar, pop-ups, GodWordStr):
nobody sits at a web server, the request hangs. Edit pages with Ed("::/Www/Index.HTM");
on the machine, or push them from your repo with tools/update_vds.py.
What the console shows
One line per request:
GET /Index.HTM 200 10049
GET /favicon.ico 404
GET /../Once.HC 403
Debug switches
Type these at any TempleOS command line, in any terminal, while the server runs. They take effect at once and are forgotten at reboot.
| Switch | Default | What it shows |
|---|---|---|
htserv_verbose=TRUE; |
FALSE |
Every request line and header, session begin and end. |
tcp_debug=TRUE; |
FALSE |
Out-of-window segments (SEQ error), bad ACKs, every retransmit and every connection TCP gives up on. |
Both print from the network path, and printing on a one-vCPU machine is slow. Turn
them on to catch a problem, then back off with =FALSE;. Left on, the Temple
spends its day reading packets aloud.
Other things worth asking the machine:
| Command | Answer |
|---|---|
TaskRep; |
Running tasks. Look for HtServ and the HtServ Session count; dozens of sessions means something holds connections open. |
"%X\n",IPv4GetAddress; |
Our address in hex (C31CB597 is 195.28.181.151). |
Host("ya.ru"); |
DNS and the route out work. |
#include "::/Apps/Wget" then Wget("http://example.com/");
|
A whole HTTP round trip out. |
When the site does not open
-
ping <IP>from your machine. No answer: network settings or the hosting firewall. - Ping answers, port 80 refused: HtServ is not running.
TaskRep;, start it again. - Opens slowly or stops opening after a while:
tcp_debug=TRUE;andhtserv_verbose=TRUE;, wait for it to happen, take a screenshot of the console. - The machine rebooted: write down what you did right before, a reboot is a triple fault and leaves nothing on the screen.
When the console keyboard does not work
You type at the VNC console and nothing happens. The keyboard is fine, the keystrokes went to the wrong window, the other console. TempleOS gives the keyboard to the window you last clicked, and over VNC the mouse lies. TempleOS has a PS/2 mouse that only knows "moved a bit", the VNC pointer and the Temple's pointer drift apart, and a click aimed left lands right.
Check it over the Confessional:
"%s\n",sys_focus_task->task_title; // the other console instead of yours
Give the keyboard back to your console. Find it in TaskRep; (after a boot from the
disk it is the one titled Tmp;), take its address and:
WinFocus(0x16774428(CTask *)); // the address TaskRep printed
"%s\n",sys_focus_task->task_title; // now your console
Do not guess the task from the window list, it is reordered every time a window comes to the top.
Without the Confessional: press Ctrl+Alt+N at the VNC console until your window is on top, it hands the keyboard to the next task. Browser consoles eat Ctrl+Alt, send it from the console's own key menu. Some tasks have no window at all (NtpDaemon, DnsOracle), the keyboard goes nowhere while one of them has it, press again.
The keyboard is yours and still nothing happens? Look at the last line of your
console. After a boot from the disk Once.HC asks Take Tour (y or n)? and waits.
It listens to Y and N only, every other key is thrown away.
Press N.
Limits
- HTTP only. No HTTPS, committees are how the CIA gets in.
-
GETonly, plusPOSTto/mcp(16 KB at most). HTTP/1.0 and 1.1, one request per connection (Connection: close). - A client gets 15 seconds to send its request, then the server hangs up.
- 16 connections may wait to be accepted at once.
- No URL decoding, so no spaces or
%20in file names. - A path with
..gets 403. Only::/Wwwis served.
Multiplayer: two Temples, one world
It is not good for the gamer to be alone. Apps/NetGame.HC is a small
covenant over UDP, port 2017, and two of God's games now know it:
-
Apps/Titanium/Titanium.HC— lockstep. Both machines fly the same world from the host's seed. Each tick the brothers exchange their hands (arrows, CTRL, SPACE, ENTER) and both Temples fly both ships from the same two hands. The host flies Terry's ship, the guest flies a second ship with a red pennant. A late packet pauses the tick; a packet lost past three seconds is forgiven and the last hand is used again. Missiles belong to the host's ship. -
Demo/Games/Wenceslas.HC— deeds over snow. The forest comes from the host's seed. Every step and every fire lit with SPACE travels as a small deed and is walked again in the brother's snow: a second king under a red pennant, two trails, left foot, right foot. The peasants are the host's: the host walks them and calls out where each one stands, ten times a second; the guest only listens. One flock, one score.
Single player is choice 1) and works exactly as before.
How to play together
-
Boot two Temples with a NIC, from an ISO built from this tree.
Once.HCbrings the network up by DHCP at boot (Netcfg;if it did not). -
The host's UDP port 2017 must be reachable by the guest: same LAN, or a port forwarded to it. Under QEMU user-mode NAT that is
GAME_PORT=2017, see below. -
On both Temples start the same game at the command line:
#include "::/Demo/Games/Wenceslas" // the snow #include "::/Apps/Titanium/Run" // the skyWenceslas shows a carol and the rules, close them with SPACE. Titanium shows the scoring, press a key.
-
The host presses
2— host a brother — and waits:Waiting for a brother... -
The guest presses
3— join a brother — and types the host's IP atBrother's IP:.The door opened. Seed received.and both worlds start.
Keys:
| Game | Walk / fly | Deed | Again | Leave |
|---|---|---|---|---|
| Wenceslas | arrows | SPACE at a tree: a Yule log | ENTER | ESC or SHIFT-ESC |
| Titanium | LEFT/RIGHT | SPACE fire, CTRL+LEFT/RIGHT missiles (host) | ENTER | ESC or SHIFT-ESC |
ENTER restarts both worlds, not just yours. Leaving with ESC tells the brother
The brother went home. You walk alone now. and he plays on alone.
If the host says The port 2017 is taken, a game was killed without leaving
(Kill, a dropped Confessional) and its socket still sits on the port. Reboot
that Temple. If the guest says No one answered, the host is not waiting yet,
or a firewall stands between you.
Two Temples on one computer
To test without a second machine, run two QEMUs from tools/run_mac.sh
(macOS: cocoa display, coreaudio). Each QEMU has its own user-mode NAT, and
inside both the Temple is 10.0.2.15; the Mac itself is 10.0.2.2. So the
host Temple gets its port 2017 forwarded to the Mac, and the guest knocks on
10.0.2.2:
tools/build_iso.py # once: out/TempleOSEE.ISO
# terminal 1: the host Temple, its UDP 2017 forwarded to 127.0.0.1:2017
GAME_PORT=2017 tools/run_mac.sh
# terminal 2: the guest Temple; the other forwards must not collide
HTTP_PORT=8687 CONFESS_PORT=2324 WG_PORT=51831 tools/run_mac.sh
Both may boot the same ISO, a CD is read only. Wait for both desktops, then
follow How to play together: in window 1 press 2, in window 2 press 3 and
type 10.0.2.2. Click a window to give it the keyboard; one person can walk
both kings, two people can share one Mac.
Two machines on one LAN under QEMU: GAME_BIND=0.0.0.0 GAME_PORT=2017 tools/run_mac.sh on the host's computer, and the guest Temple types that
computer's LAN address.
On Linux the same by hand, with QEMU's own window and no coreaudio:
qemu-system-x86_64 -machine pc -m 2048 -smp 2 -cdrom out/TempleOSEE.ISO -boot d \
-netdev user,id=u1,hostfwd=udp:127.0.0.1:2017-:2017 -device pcnet,netdev=u1
qemu-system-x86_64 -machine pc -m 2048 -smp 2 -cdrom out/TempleOSEE.ISO -boot d \
-netdev user,id=u1 -device pcnet,netdev=u1
Limits
- The packets are plain UDP, not sealed like WireGuard or TLS. The CIA can watch your ship turn left and count your peasants. Let them. It is a game, and God keeps the score.
- Two brothers, not three. One host, one guest.
- The windows should be the same size on both Temples: the forest and the peasants' field are laid out by the window. The default window is.
- Titanium: in this build the sky freezes after up to a minute even alone, even
Terry's untouched copy. The CPU0 share of the drawing, given to Adam by
JobQue, never comes back and the window manager waits for it forever. Not NetGame's sin; it is being hunted. Wenceslas does not useJobQueand walks on.
tools/patch_mp.py is the graft that sewed the multiplayer in: pure-ASCII
inserts into Terry's CP437 files, the high-byte count checked unchanged. Run it
on Terry's originals and it writes both games again, byte for byte.