hostdoc
v1.3.0
Published
Publish a local HTML file or folder to your own AWS and get a short shareable link.
Readme
hostdoc
Publish a local HTML file or folder to your own AWS and get a short shareable link.
hostdoc has three hosting modes that share one publish path — you pick a mode by how you configure it, and the mode is derived, never stored:
- No-domain (S3 website) — an HTTP link served straight from a public S3 static-website bucket. Set up with
hostdoc setup. - Domain (CloudFront) — HTTPS on your own domain from a private S3 bucket fronted by CloudFront (OAC), provisioned with Terraform.
- Self-hosted — publish to a local directory served by your own Caddy/nginx on your NAS or PC. No AWS involved.
Install
npm install -g hostdocQuick start (no domain)
Requires AWS credentials available to the SDK (env vars, a shared profile via --profile, or SSO).
# 1) Create a public website bucket and save config
hostdoc setup --bucket my-unique-bucket --region us-east-1
# 2) Publish
hostdoc publish ./report.html # → http://<bucket>.s3-website-...amazonaws.com/<code>/
hostdoc publish ./site/ --slug aws-design
hostdoc publish ./site/ --slug team/q1/report # nested path → .../team/q1/report/
# 3) Manage
hostdoc list
hostdoc open aws-design
hostdoc rm aws-design --yes--dry-run prints the URL it would publish to without uploading — and without any AWS call, so it works offline / with no credentials configured.
open builds and opens the URL without verifying the document exists; an unknown id just opens a 403/404 page. rm asks for confirmation before deleting — pass --yes to skip it (required when stdin is not a TTY).
Note: no-domain mode serves content publicly over HTTP (S3 website endpoints do not support HTTPS). For public-facing HTTPS, see Domain mode below.
Domain mode (HTTPS via CloudFront)
Domain mode serves your docs over HTTPS from a fully private S3 bucket fronted by CloudFront (OAC). It is provisioned with Terraform.
Prerequisites: a Route53 hosted zone for your domain, AWS credentials, and Terraform installed. No repo checkout needed — the Terraform templates ship with the npm package and are extracted for you.
hostdoc provision \
--hosted-zone example.com \
--subdomain shared \
--region us-east-1
# extracts bundled Terraform into ~/.local/state/hostdoc/infra, writes
# terraform.tfvars.json from the flags, then runs terraform init + apply and saves
# the config (~15-30 min).
# non-interactive (e.g. driving hostdoc from an agent): add --approve
hostdoc publish ./mydoc # → https://shared.example.com/<code>/The templates land in a per-user, cwd-independent directory by default —
$XDG_STATE_HOME/hostdoc/infra (i.e. ~/.local/state/hostdoc/infra) — so the
single local terraform.tfstate is reused no matter where you run hostdoc
from, and deprovision always finds it. Override with --dir. Re-running
provision never clobbers a dir you have already edited. Optional
--price-class overrides the default PriceClass_100.
Already provisioned the infra yourself? Import it without applying:
hostdoc init --from-terraform <dir>.
Tear it all down with hostdoc deprovision (it reuses the terraform.tfvars.json
written during provision; or pass the same flags). Add --approve to run it
non-interactively.
Overwriting (--force) and hostdoc rm automatically invalidate
/<code>/* on the distribution.
External (non-Route53) DNS
Automated ACM validation and alias records require a Route53 hosted zone. If your domain is hosted elsewhere (e.g. Cloudflare), provisioning is manual: add the ACM validation CNAME shown by AWS, then point your subdomain at the CloudFront distribution domain via a CNAME/ALIAS record. This is outside the automated path.
Security note
The Terraform publisher_policy_json output is a minimal IAM policy for
publishing. Prefer a dedicated IAM user (create_publisher_user = true) over
root credentials for day-to-day hostdoc use. Enabling it stores the
access-key secret in plaintext in terraform.tfstate; keep state private and
rotate/destroy the key when done.
Self-hosted mode (your own NAS/PC)
Self-hosted mode publishes to a local directory served by your own web
server — no AWS at all. hostdoc copies files into <serve-root>/<code>/ and
returns a link on your own host.
# Configure the serve directory and print a Caddy (default) or nginx snippet
hostdoc setup --serve-root /srv/hostdoc --host docs.example.com
# → paste the printed snippet into your web-server config, then reload it
hostdoc publish ./report.html --slug aws-design # → http://docs.example.com/aws-design/--host is your public host (a DDNS name, domain, or static IP). Add --port
for a non-standard port and --scheme https if your server terminates TLS.
--nginx emits an nginx server block instead of a Caddyfile (nginx is also
auto-selected when it is on PATH); --caddy forces a Caddyfile.
Auto-install (Caddy only). Add --install and hostdoc downloads Caddy and
registers a boot service (Linux/macOS/Windows) so it survives reboot:
hostdoc setup --serve-root /srv/hostdoc --host docs.example.com --installNon-privileged prep (config, Caddyfile, binary) runs as your user; the
privileged service step runs automatically when you are root/admin, otherwise
hostdoc prints the exact sudo (or elevated PowerShell) commands to finish. An
--nginx choice falls back to the manual snippet — nginx is not a single static
binary.
Tear it down with hostdoc deprovision (stops and unregisters the service;
published files and the Caddy binary are left in place). Only the serve
directory is served — directory listing is off and /_* (hostdoc's _meta
sidecars) is blocked.
Network exposure — port-forwarding, firewall, router — is your responsibility. Expose only what you intend.
Use with an agent (skill)
hostdoc ships an installable agent skill
so coding agents can drive it conversationally — "publish this folder", "list my
docs", "remove that slug" — without memorizing flags.
npx skills add jkas2016/hostdocThis installs the hostdoc skill into your agent. The skill shells out to the
hostdoc CLI, preferring a global install and falling back to npx -y hostdoc,
so no global install is required. It runs an AWS-free preflight check and
turns missing config/credentials into guidance instead of raw errors.
Example prompts: "publish ./report.html and give me the link", "list my published docs", "open aws-design", "remove aws-design".
Credentials
hostdoc never stores AWS keys. It uses the AWS SDK default credential chain (environment variables → SSO → shared ~/.aws profile). Select a profile with --profile <name> and a region with --region <region>.
Configuration precedence
Flags (--bucket/--region/...) > HOSTDOC_* env vars > ~/.config/hostdoc/config.json.
Precedence merges fields, but the mode is derived from the merged
result (domain+distribution → cloudfront; serveRoot → self-hosted; else
bucket+region → s3-website). So setting only HOSTDOC_BUCKET on top of a
cloudfront config file does not switch to s3-website — the file's domain
still wins the derivation, and the bucket is ignored for mode (hostdoc prints a
warning when it detects this).
To pin the mode regardless of which fields merged in, use --mode or
HOSTDOC_MODE (s3-website | cloudfront | self-hosted, case-insensitive):
# force s3-website for a one-off, even though the config file is cloudfront
HOSTDOC_BUCKET=demo-bucket HOSTDOC_REGION=us-east-1 \
hostdoc publish ./x.html --mode s3-websiteA forced mode validates only that mode's required fields and ignores the others (printing a note about what it ignored).
License
MIT
