Server Guide
The hostedat server is a single binary that handles everything: serving static sites, managing users, handling HTTPS, and exposing the API. No reverse proxy, no Docker, no external dependencies.
Quick start
Download the server binary for your platform from the downloads page, create a config file, and run it.
Choose your engine
The server ships with two JavaScript engine options for the worker runtime:
- V8 (recommended) — JIT-compiled JavaScript for best worker performance. Available for Linux and macOS.
- QuickJS — Interpreted JavaScript, runs on all platforms including Windows. No native dependencies required.
Both engines provide the same Workers API and features. If you don't use workers, either engine works identically for static site hosting.
# V8 (recommended) — amd64
curl -fsSL https://docs.hostedat.ditto.moe/downloads/hostedat-server-v8-linux-amd64 -o hostedat-server
# V8 (recommended) — arm64
curl -fsSL https://docs.hostedat.ditto.moe/downloads/hostedat-server-v8-linux-arm64 -o hostedat-server
# QuickJS — amd64
curl -fsSL https://docs.hostedat.ditto.moe/downloads/hostedat-server-linux-amd64 -o hostedat-server
# QuickJS — arm64
curl -fsSL https://docs.hostedat.ditto.moe/downloads/hostedat-server-linux-arm64 -o hostedat-server
chmod +x hostedat-server # V8 (recommended) — Universal binary (Apple Silicon + Intel)
curl -fsSL https://docs.hostedat.ditto.moe/downloads/hostedat-server-v8-darwin-universal -o hostedat-server
# QuickJS — Universal binary (Apple Silicon + Intel)
curl -fsSL https://docs.hostedat.ditto.moe/downloads/hostedat-server-darwin-universal -o hostedat-server
chmod +x hostedat-server # QuickJS only (V8 is not available on Windows)
# amd64
Invoke-WebRequest -Uri https://docs.hostedat.ditto.moe/downloads/hostedat-server-windows-amd64.exe -OutFile hostedat-server.exe
# arm64
Invoke-WebRequest -Uri https://docs.hostedat.ditto.moe/downloads/hostedat-server-windows-arm64.exe -OutFile hostedat-server.exe Then create a config and start the server:
cp config.example.yaml config.yaml
# Edit config.yaml with your settings
./hostedat-server First-run setup
On first launch with an empty database, the first user to register becomes the superadmin. This account has full control and cannot be demoted.
- Start the server
- Open the web UI at your configured domain
- Register the first account — this is your superadmin
- Configure registration settings (open, invite-only, or closed)
HTTPS & certificates
hostedat uses CertMagic (the ACME library from Caddy) to automatically obtain and renew wildcard TLS certificates from Let's Encrypt. This requires DNS-01 validation via Cloudflare.
# Listen on :443 for production HTTPS
listen: ":443"
# Cloudflare API token with Zone:DNS:Edit permission
cloudflare:
api_token: "your-cloudflare-api-token"
The server will automatically obtain a wildcard cert for *.yourdomain.com and renew it
before expiration. No cron jobs, no manual renewal.
Development mode (no TLS)
For local development, listen on a non-443 port and leave the Cloudflare token empty:
listen: ":8080"
cloudflare:
api_token: "" Database
hostedat uses GORM with SQLite by default. The database file is created automatically. For production, you can switch to PostgreSQL or MySQL by changing the driver and DSN:
# SQLite (default)
database:
driver: sqlite
dsn: ./data/hostedat.db
# PostgreSQL
database:
driver: postgres
dsn: "host=localhost port=5432 user=hostedat dbname=hostedat sslmode=disable"
# MySQL
database:
driver: mysql
dsn: "hostedat:password@tcp(localhost:3306)/hostedat?parseTime=true" Static site features
hostedat supports several features that make it compatible with sites built for Netlify or Cloudflare Pages.
_redirects file
Place a _redirects file in the root of your uploaded site to define redirect and rewrite rules:
# Redirects (browser URL changes)
/old-path /new-path 301
/blog/* /new-blog/:splat 302
# Rewrites (transparent, URL stays the same)
/api/* https://api.example.com/:splat 200
# SPA fallback (must be last)
/* /index.html 200 301/302— redirect (browser URL changes)200— rewrite (serve target content at original URL)*wildcard is captured and available as:splat- First match wins, evaluated top-to-bottom
- Static files always take precedence over rules
_headers file
Custom response headers for matching paths:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
/*.js
Cache-Control: public, max-age=31536000, immutable Custom 404
Include a 404.html file in your upload to show a custom 404 page when no file matches.
SPA mode
Toggle SPA mode per-site via the dashboard or API. When enabled, all unmatched routes
serve index.html — equivalent to having /* /index.html 200 as the last
_redirects rule.
Worker runtime
hostedat includes a Cloudflare Workers-compatible server-side JavaScript runtime. Include a
_worker.js file in your deployment to intercept HTTP requests with JavaScript instead
of serving static files directly. This enables dynamic content, API endpoints, authentication,
server-side rendering, and more.
Workers have access to environment variables, KV storage, cron triggers, and the ASSETS
binding to serve static files when needed. See the full Worker Runtime documentation
for API reference, examples, and lifecycle details.
User roles
| Role | Capabilities |
|---|---|
| superadmin | Full control. First registered user. Cannot be demoted. |
| admin | Manage users, sites, invites. Can be promoted/demoted by superadmin. |
| user | Create sites, deploy, manage own API keys. |
Running as a service
For production, run hostedat as a systemd service:
[Unit]
Description=hostedat static site hosting
After=network.target
[Service]
Type=simple
User=hostedat
WorkingDirectory=/opt/hostedat
ExecStart=/opt/hostedat/hostedat-server
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target sudo systemctl enable hostedat
sudo systemctl start hostedat Next: Configuration Reference for all config options.