Have you treated a free shared server like a private lab? I still hear that claim in tooling threads. It sounds efficient, but it is usually a leak.
This FAQ attacks repeated runtime claims about free boxes. Each answer has a check you can run today. No latency folklore. No eval-score theater.
Need a throwaway model and a throwaway host for rehearsal? I use MonkeyCode's free model access and free server option for that drill only. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Strip the product name. The checks still stand.
What question are we actually answering?
Who owns the blast radius when the box misbehaves? That is the only question. Pretty dashboards do not answer it. A green HTTP status does not answer it either.
I want evidence from headers, processes, and env. I do not want a story about "it is just a demo." Demos leak. Demos get bookmarked. Demos become shadow staging.
Q: If the URL is obscure, is the box private?
Claim people repeat: nobody else knows the hostname, so we are fine.
Evidence: send a boring HEAD request. Read what the box admits.
curl -sI "$FREE_BASE_URL" | sed -n '1,20p'
Look at Server, Via, X-Request-Id, and cookie scope. Shared edges love to introduce themselves. An unlisted URL is not a tenancy boundary. It is a bookmark.
Corrected model: privacy is control of tenants, memory, and logs. Obscurity is none of those. If you cannot name the other tenants, assume they exist.
Q: Can the free server hold my real secrets?
Claim people repeat: env vars on a demo box are a vault.
Evidence: print names, never values. Then refuse the run.
env | awk -F= '
toupper($1) ~ /(KEY|TOKEN|SECRET|PASSWORD|PRIVATE)/ { print $1 }
'
Did that list surprise you? Then the box already lost. A free shared host may snapshot env. It may write crash dumps. It may expose debug pages after a restart.
Corrected model: secrets live in a manager you control. The free box gets a short-lived dummy. If the dummy leaks, you shrug. If the real token leaks, you rotate and write an incident.
I refuse to export production credentials into a box I do not patch. Do you still paste them "just once"?
Q: Does a 200 mean my prompt is portable?
Claim people repeat: the free model answered, so any model will.
Evidence: pin what came back, not what you hoped.
curl -sS "$FREE_BASE_URL/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "X-Run-Id: $(uuidgen)" \
--data '{"messages":[{"role":"user","content":"Reply with PING only."}]}' \
| python -c 'import sys,json; d=json.load(sys.stdin); print(sorted(d.keys())); print((d.get("model") or d.get("id") or "unknown")[:80])'
A 200 is transport success. It is not a contract. System prompts differ. Tool schemas differ. Refusal styles differ. Your golden reply can vanish on the next route.
Corrected model: portability is a fixture plus a diff. Save request id, model field, and raw text. Compare them on the next host. Do not trust memory. Memory lies faster than logs.
Q: If there is no SLA, can I skip tests?
Claim people repeat: free means best effort, so tests are waste.
Evidence: free stacks fail in cheap, boring ways. Timeouts. Cold starts. Empty bodies. Truncated streams. Those failures still ship into your agent loop.
for i in 1 2 3 4 5; do
curl -sS -o /tmp/free_body_$i -w "%{http_code} %{time_total}\n" \
--max-time 8 "$FREE_BASE_URL/healthz" || echo "fail $i"
done
Five cheap probes beat one hopeful click. You are not measuring a vendor promise. You are measuring whether your client retries like an adult.
Corrected model: missing SLA means more client tests, not fewer. Timeouts, idempotency keys, and backoff are the product now. The model is a dependency. Treat it like DNS. DNS is free. DNS still needs retries.
Q: Can my agent keep memory on that disk?
Claim people repeat: the workspace will still be there tomorrow.
Evidence: write a canary file. Read it back. Then inspect mount options.
echo "canary-$(date -u +%s)" > /tmp/freebox_canary.txt
cat /tmp/freebox_canary.txt
df -hT .
mount | awk '$3=="/" || $3=="/tmp" { print }'
Ephemeral disks vanish. Shared disks mix leftovers. Both break "the agent will remember." Chat history is not a volume claim. Have you confused them yet?
Corrected model: durable state lives in a store you name. Object storage. Your repo. Your queue. The free box is a CPU rental. Rentals get wiped.
Q: Is "shared" the same as "sandboxed"?
Claim people repeat: containers isolate everything that matters.
Evidence: a container without a policy is a polite process. Check user, network, and outbound identity.
id
umask
ps -eo user,pid,args | head
curl -sS https://ifconfig.me/ip || true
Same outbound IP as strangers? Then abuse from neighbors can brand you. Same uid namespace as a noisy roommate? Then your files are a rumor. Sandbox is a policy. It is not a Docker logo.
Corrected model: isolation is a checklist with owners. Network egress. Filesystem mounts. Secret injection. Log retention. If any row is "unknown," the box is a group project.
Artifact: a 20-minute isolation probe
This is a proposed script. I am not selling a score. Label it unexecuted until you run it on your box.
#!/usr/bin/env python3
"""Proposed free-box isolation probe. Unexecuted example.
Never prints secret values. Exits nonzero on hard fails.
"""
from __future__ import annotations
import json
import os
import re
import sys
import time
import urllib.error
import urllib.request
from pathlib import Path
SECRET_NAME = re.compile(r"(KEY|TOKEN|SECRET|PASSWORD|PRIVATE)", re.I)
BASE = os.environ.get("FREE_BASE_URL", "").rstrip("/")
def fail(msg: str) -> None:
print(f"FAIL {msg}")
sys.exit(2)
def warn(msg: str) -> None:
print(f"WARN {msg}")
def ok(msg: str) -> None:
print(f"OK {msg}")
def check_secrets_named_not_sent() -> None:
named = [k for k in os.environ if SECRET_NAME.search(k)]
if named:
fail("secret-shaped env names present: " + ",".join(sorted(named)[:12]))
ok("no secret-shaped env names in this process")
def check_canary_disk() -> None:
p = Path("/tmp/freebox_canary.txt")
token = f"canary-{int(time.time())}"
p.write_text(token, encoding="utf-8")
if p.read_text(encoding="utf-8") != token:
fail("canary file roundtrip failed")
ok("canary file roundtrip worked; still do not trust reboot")
def check_http_identity() -> None:
if not BASE:
warn("FREE_BASE_URL unset; skip HTTP identity")
return
req = urllib.request.Request(BASE, method="HEAD")
try:
with urllib.request.urlopen(req, timeout=8) as resp:
headers = {k.lower(): v for k, v in resp.headers.items()}
except urllib.error.URLError as exc:
fail(f"HEAD {BASE} failed: {exc}")
rid = headers.get("x-request-id") or headers.get("x-amzn-trace-id")
server = headers.get("server", "missing")
if not rid:
warn("no request id header; you cannot correlate incidents")
else:
ok(f"request id present ({rid[:24]}...)")
ok(f"server header={server!r}")
def main() -> None:
check_secrets_named_not_sent()
check_canary_disk()
check_http_identity()
report = {
"mental_model": "rental CPU, not staging",
"next": "put durable state somewhere you can name",
}
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()
Run it like this. Keep real secrets out of the shell.
chmod +x probe_free_box.py
env -u AWS_SECRET_ACCESS_KEY -u OPENAI_API_KEY \
FREE_BASE_URL="https://example.invalid" python3 probe_free_box.py
The script fails closed on secret-shaped names. That is the point. A demo that needs production keys is not a demo. It is an incident rehearsal with worse lighting.
Decision table: when the free box is allowed
Use this table before you type export.
| Situation | Free shared box? | Why |
|---|---|---|
| Prompt wording experiments | Yes | Output is disposable |
| Teaching the isolation probe | Yes | Failure is the lesson |
| Customer PII in the payload | No | Tenancy is unknown |
| Production deploy keys in env | No | Logs and dumps are not yours |
| CI gate that ships to users | No | Stability and identity are unknown |
| Agent memory you must keep | No | Disk may vanish or be shared |
| Retry and timeout client tests | Yes | You are testing your wrapper |
If two rows conflict, the "No" row wins. Why would a wording experiment need a deploy key? It would not.
Corrected mental model
A free model is a borrowed brain. A free server is a borrowed room. Borrowed rooms get other guests. Borrowed brains change their answers.
I keep three labels on every run:
- Rental — CPU and tokens I can lose today.
- Fixture — request id, raw body, model field.
- Store — the only place durable facts may live.
Mix those labels and you get folklore. Folklore ships incidents. Do you still call the rental "staging" in Slack?
Staging has owners, patches, and access lists. A free box has a URL. Those are not the same type. Stop casting them.
Limitations, and who should not use this
This FAQ does not prove a vendor is safe. HEAD headers can lie. Disk canaries do not prove tenancy. My script never inspects other users. That would be a different, uglier article.
Do not use this approach if you handle regulated data. Do not use it for production traffic. Do not use it as a penetration test against a host you do not own. Do not use it to justify skipping retries.
Also skip it if you need a contractual uptime number. A probe cannot mint an SLA. It can only show that you still need one.
The examples are labeled proposals. Run them on machines you control. Replace example.invalid before you expect a useful HEAD.
What I want you to do next
Pick one live free box you already use. Run the env-name grep first. If that check fails, stop. Rotate. Then come back and argue with the table.
Which question failed first on your box?
Top comments (0)