Advanced settings
For where to run a small box and where settings go, see deployment profiles.
The installer supplies the required database connection and admin key; you choose the address and sign-in methods. The tables state the binary defaults. This folder explains each advanced feature in plain terms, lists every setting that changes it, and gives recipes for common changes.
Easiest start: the setup helper at https://simple-host.app/setup?product=small-box. It asks a few questions (or every question, in Advanced mode), keeps the default for anything you skip, and writes the one-line install command and the .env for a small box. Nothing is required: with no domain yet, the command installs the box in setup mode, which asks for the domain in the browser afterwards, and any value only you can know is left in the .env as a blank under a # Fill in: line, named in one line above it. It runs in your browser and never asks for a password or key. Just before your files it can check your choices for likely mistakes (a setting that weakens sign-in, a retention or undo promise cut short, an upload size the box cannot hold): it sends only the names and values of the numbers, durations, switches, choices and limits you changed, never hostnames, emails or secrets, and you Apply or Ignore each suggestion. You can skip it; where the server has no model backend it is skipped by itself. The files step also gives one block to hand to your own AI agent: what the server needs, every step with your files in it, and how to check the result.
For Simple Host Enterprise (https://simple-host.app/setup?product=enterprise), choose
Helm or Kubernetes YAML for a cluster you already run. Both use the same chart and its
values.yaml; the page does not create cloud infrastructure. Connect existing Postgres
with its CA certificate or install one persisted Postgres in the cluster for evaluation.
The latter has no automatic backups. Connect your existing S3-compatible bucket, company
OIDC provider, ingress and certificate issuer. The bucket starts with no provider assumed.
Nothing must be filled in to reach the files: defaults stay, and the page names the blanks
you must complete before installation. Secrets are filled locally in secrets.env and put
in a persistent Kubernetes Secret; the browser never receives them. Generate signing and
envelope keys once and retain them for upgrades. With external Postgres, use its existing
owning-role password and a distinct application-role password. Its CA goes in db-ca.crt,
passed to Helm with --set-file postgres.external.caCert=db-ca.crt.
Advanced settings map to the chart’s typed values or extraConfig; secrets go in the
existing Secret. The chart also exposes resources, replicas, scheduling and optional
annotations for an existing workload identity. Bucket identity uses the AWS SDK credential
chain; other S3-compatible providers need S3/HMAC keys. Select the existing kubeconfig
context and namespace, then run the install or render/apply commands. After /readyz
answers, finish the Enterprise guide’s admin sign-in and make smoke check. When owner
certificates come from an internal CA, the browser and the machine running that check must
trust it (CURL_CA_BUNDLE for curl). Cost estimates: https://simple-host.app/costs.
Where to run a small box
Any fresh Ubuntu server with a public IPv4 address works. We recommend UpCloud: the smallest UpCloud server (1 CPU, 1 GB, about $4/month) runs Simple Host comfortably; we test on it. Create your UpCloud account — $25 in credits (referral link. New accounts through this link get $25 of UpCloud credit; their terms apply.)
- Create your UpCloud account.
- In the UpCloud control panel, create an API token (Account → API tokens; recommended, it can have an expiry and an IP allow-list) or an API user (a sub-account with API access allowed, with only the server permissions it needs). If you can, allow only your own IP address.
- Answer the questions at https://simple-host.app/setup?product=small-box, with UpCloud as where it runs.
- On the files step, run one of the two lines it gives in your own terminal: the first asks for
the token and keeps it there as
UPCLOUD_TOKEN(whichupctlreads), the second asks for the API user’s name and password and keeps them asUPCLOUD_USERNAMEandUPCLOUD_PASSWORD. Start your AI agent in that terminal and give it the prompt. The agent tells you the plan and its price (fromGET /1.3/price) before creating anything, creates the smallest Ubuntu 24.04 server withupctlor the UpCloud API and your SSH key, has you add the DNS records (A records for your domain and*.<domain>, pointing at the server), runs the installer from its pinned release with your choices, checks/healthz, HTTPS and the release, and tells you the admin page. If anything fails, paste the error at https://simple-host.app/setup?product=small-box#help. - When the server is up, run
unset UPCLOUD_TOKEN UPCLOUD_USERNAME UPCLOUD_PASSWORDin that terminal (or close it): until then every program started there can read them.
The setup page never asks for or accepts UpCloud credentials.
After the install. The installer prints the admin key; it is also kept on the server as
ADMIN_API_KEY in /opt/simple-host/.env, and re-running the installer prints it again. Open
https://<domain>/admin and paste it there to sign in as the admin. The admin page names the
release the box runs; on the server this says the same (simple-host is not a command on the
server itself):
cd /opt/simple-host && sudo docker compose exec -T app simple-host version
The admin’s own sites live under the domain’s first label (sites.<domain>/<label>/<site>/), or
organiser when that label is reserved.
Where settings go
- Small box (Docker Compose,
deploy/install/install.sh):/opt/simple-host/.env, thencd /opt/simple-host && sudo docker compose up -d. Re-running the installer (which is also the upgrade) keeps what you added. The installer’s flags set the address (--host,--content), the certificate email (--email), the largest site (--max-site-mb) and versions kept (--keep-versions). - Your own build: the server’s environment (a systemd
EnvironmentFile, for example), then restart.
A value that does not parse, is out of range, or does not fit another setting stops the server at startup with a message naming it. Every setting changed from its default is printed once in the startup log. Emails, pages, the served skills and the connector’s descriptions state the value in force.
Areas
| Area | What it covers |
|---|---|
| Server and addresses | The domain, the separate content host, per-person and per-site addresses, setup mode |
| Accounts and sign-in | Owner sign-in (email codes, Google), API keys, visitor sign-in, AI app connections |
| Sites and versions | Site and upload size, versions kept, preview and download links, sites per account |
| Saved data | What pages save, undo and history, size limits, who may write |
| Storage migration plan | Shipped KV, SQLite and files resources; exact legacy behavior that needs redesign before any owner-directed migration |
| Domains and certificates | Custom domains, address families, their checks and release, certificates |
| Cleanup and retention | Recently deleted, idle-site cleanup, how long analytics are kept |
| Sending email with Resend, the sender, reply-to | |
| Storage and backups | The database, the site files, what to back up |
| Observability | Health, the startup log, the admin page, analytics |
| Rate limits | Every rate limit in one table |
Keeping this in sync
settings.json is generated from the code (simple-host settings --json); the
tables on these pages and the setup helper are checked against it by make check.
Configuration is the entry page for the ten registry areas.
After changing a setting in code, run
bash scripts/sync-settings.sh and commit what it changes. The setup helper’s copy of the
enterprise settings comes from an enterprise checkout
(ENTERPRISE_REPO=/path/to/simple-host-enterprise bash scripts/sync-settings.sh).
Your home page (2026-10-05): home selection, public showcase feed, bio, pins and manual order also work on small-box path installs. The public person page opens the selected site’s usual URL; the owner dashboard keeps its own origin. No whole-space domain is included. See Your home page.
Defaults in <angle brackets> are derived from other settings. Server, sign-in,
email and other non-knob settings are read by internal/config/config.go;
MAX_ARCHIVE_MB and KEEP_VERSIONS are read by the handler.
Operational times and limits
Every operational time and limit Simple Host enforces can be changed per install with an environment variable. Unset (or blank) means the value in the generated Default column. Hosted installations may override these defaults.
- Where they are read. Once, at startup, in
internal/config/limits.go(Knobs()is the list). A value that is not a whole number, is out of range, or does not fit with another setting stops the server with an error naming the variable, rather than running with a value nobody chose. Every knob that differs from its default is printed once in the startup log (limits changed from the defaults: ...). - Where to set them. simple-host.app:
/etc/simple-host.env, then restart. Docker Compose anddeploy/install/install.shboxes:/opt/simple-host/.env(.env.examplelists them commented out;compose.yamlpasses each one through; the installer keeps them on a re-run), thendocker compose up -d. - What they change. The enforcement and every sentence that states the value: emails, the
owner app, the landing and feature pages, the privacy page, the admin page,
llms.txt, the OpenAPI spec, the skills served from this install, and the connector’s MCP instructions, tool descriptions and results. Served pages and documents are written with the defaults and rewritten when served (internal/handler/limitstext.go, the same way the hostnames are rewritten for an instance on another domain); with every knob at its default nothing is rewritten. The skills published to the Claude and ChatGPT plugin directories describe simple-host.app and keep its values. - Units. Units are in the setting names (
_MINUTES,_HOURS,_DAYS); counts are whole numbers. See Rate limits for the<burst>,<every>format. - Changes apply to new deletions and warnings. The date a person was promised is stored
when the promise is made: a deleted site keeps its purge date (
DELETED_RETENTION_DAYS), an idle-warned site its removal date (IDLE_GRACE_DAYS), a failing domain whose owner was emailed its disconnect date (DOMAIN_LAPSE_HOURS). Shortening one never removes anything earlier than its email said; lengthening one does not extend what was already promised. Likewise, tightened token and session lifetimes (OAUTH_*_TTL_*,VISITOR_SESSION_*,PREVIEW_LINK_TTL_MINUTES,EXPORT_LINK_TTL_MINUTES,SIGNIN_CODE_TTL_MINUTES) don’t shorten ones already issued: each carries the expiry it was issued with. - Skills and cached copies. The skills served from this install state its limits, but their
advertised version (
/skills/version) follows the skills’ text, not the settings, so an agent that already installed them keeps the old numbers until it reinstalls. Reinstall the skills (or tell people to) after changing a limit they state.