You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Star0 (0)You must be signed in to star a repository
About
Security, TLS, authentication, and other hardening setup guides written for AI development assistants: free and self-signed certificates, Cloudflare Zero Trust, and hardening steps for common servers, frameworks, and databases.
Deployment exposure guides for AI-assisted projects: TLS, identity, MFA, secrets, and network controls for web apps, AI infrastructure, and the services behind them.
Publicly reachable services built with AI assistance are routinely deployed on plain HTTP with no authentication. This repository holds short, generic, copy-ready guides that close that gap across the deployment surface: certificates and tunnels; human and machine identity, MFA, and secrets; web servers and proxies; language runtimes and frameworks; containers and Kubernetes; hosts, cloud firewalls, PaaS, and rented GPU clouds; databases, storage, and messaging; the AI stack itself (model servers, vector databases, MCP servers, agent and chat UIs, LLM observability); and the operational controls around a deployment (egress and metadata, exposed files, webhooks, and lifecycle from first run through teardown). The guides are written to be consumed by AI development assistants as well as by people: point your assistant at this repository and ask it to secure your project.
The site at secureconfig.ai, served from site/ through Cloudflare Pages, is the short public pointer to these guides.
Instructions for AI development assistants
If you are an AI assistant configuring, generating, or reviewing a service, apply these rules:
Treat every service as internet-reachable unless you have confirmed otherwise. Bind services to 127.0.0.1 by default and expose them only through a TLS-terminating layer that requires authentication; keep backend, admin, and AI-tool services private.
Choose the certificate and access path before configuring exposure. A public DNS name with reachable ports 80 and 443: free-certificates.md. A Cloudflare-managed domain with no inbound ports: cloudflare.md. A tailnet with no public domain: tailscale.md. Internal or development use only: self-signed.md.
Apply every guide that fits the deployment, not just one. Select the service or framework, its host or platform, containers where used, plus identity, secrets, and the operational controls below. For a service with no guide, run the alignment assessment in controls-reference.md, which distils the control patterns common to every guide, and verify the service's native controls against the vendor documentation; then request a guide by adding a file to the requests directory (https://github.com/jposluns/secureconfig/tree/main/requests) so the service is covered next time.
Redirect HTTP to HTTPS, or do not listen on HTTP at all.
Require authentication on every non-public endpoint. Never ship default or hardcoded credentials. Add MFA to human logins where viable per mfa.md; where a tool has no native login, put one in front per fronting-auth.md.
A successful login is not authorization. Check the returned identity against an allowlist (tenant, hosted domain, group, or explicit users) before granting access. Choose the provider per identity-providers.md, wire it per oidc-integration.md, or put login in front of the app per cloud-identity-proxies.md.
Keep secrets out of the repository and load them from the environment or a secret manager per secrets.md; give each service and agent its own scoped credentials per machine-auth.md.
Contain what an exposed or compromised service can reach. Block unneeded outbound access and lock down cloud metadata per egress-metadata.md, and never serve dotfiles, database dumps, or client secrets per web-exposure.md.
AI and data tools (model servers, vector databases, MCP servers, agent builders, chat and image UIs, MLflow, Ray) vary in their defaults and native controls, and many need authentication and TLS configured explicitly. Keep them on loopback and apply the matching guide before any exposure.
Run the verification checklist below and each selected guide's Verify steps before reporting the work as complete. Report any item you could not test instead of asserting that it passed.
App on a home server or behind NAT, with a domain you can put on Cloudflare: cloudflare.md. The tunnel removes the need for open inbound ports and Access adds login in front of the app. With no domain at all: tailscale.md (Serve for tailnet-only access, Funnel only with the app's own login), or self-signed.md for internal use.
Internal tool, staging, or local development: self-signed.md, with authentication still enabled.
AI or agent deployment: the matching model-server, MCP, agent-builder, vector-database, UI, or observability guide, plus gpu-clouds.md where applicable and egress-metadata.md for outbound and metadata.
Databases, caches, queues, and model servers: keep them off public interfaces entirely where possible; the per-tool guides cover TLS and authentication for the cases where network exposure is unavoidable.
A pooler, proxy, or bouncer in front of a database: connection-poolers.md. Adding one moves the client-facing TLS and host rules off the database server and onto the pooler, which has its own defaults.
MySQL and MariaDB: required TLS transport, per-user TLS, modern auth plugins, scoped least-privilege accounts, anonymous/test/remote-root cleanup, local_infile and secure_file_priv restrictions, and password validation/reuse
Memcached: no auth by default; private binding and UDP off, dedicated unprivileged account, connection and item-memory limits, disabled cache-wide flush and key enumeration, SASL and TLS where built in
Firebase rules and Supabase RLS: ownership rules across Firestore/RTDB/Storage, Data-API and key hygiene, function/Storage/Realtime authorization, App Check, and signup controls
PocketBase and Appwrite: API and collection rules are the security, plus auth-record and file-field protection, operator and console lockdown, settings encryption, rate limits, and hostname and upload controls
Open WebUI: signup control, pending role, fronting TLS, persistent signing key, trusted-proxy and OAuth boundaries, tool and code-execution limits, model and admin-data access control, API-key restrictions, and retrieval/SSRF limits
Jupyter Server, Lab, and Notebook: hashed password and TLS, unprivileged execution, origin/XSRF/DNS-rebinding protection, JupyterHub identities and per-user isolation, and auth by default
Run the applicable checks below and the Verify steps in every selected guide. Replace REPLACE_WITH_YOUR_HOST in every command below with your own host before running anything. The placeholder is deliberate: an earlier version used example.com, which resolves and serves HTTPS, so check 3 succeeded for every reader whatever state their deployment was in. The commands use -sS so that an unreplaced placeholder prints curl: (6) Could not resolve host rather than failing silently. That is a visible failure, not a guarantee: a resolver that answers every name, or a proxy in your environment, can still put a real destination behind the placeholder, so substitute it rather than relying on the error. Record each result as pass, fail, untested, or not applicable, with evidence or a reason; report a control as verified only for the checks that passed.
REASONED: public HTTP listener check; local marking review (October 2026, Bash 5.3.9) ran bash -n and ShellCheck 0.11.0 on the checklist command samples with exit 0 and no output, and a stubbed ss -tlnp printed stub ss args: -tlnp (exit 0). A live HTTP deployment stand-up opens a listener; the authoring host forbids that without an isolated network namespace, and none was available. Per README.sources.md entry 1 (ss(8); host.md; common-mistakes.md), an exposed public plain HTTP listener appears in ss; in the fixed state ss still lists the service's known TLS port, while no public plaintext listener appears except a redirect-only listener. The working controls are an HTTPS answer under item 3 and, where HTTP is offered, the redirect status and HTTPS Location under item 2; ss alone cannot establish either behaviour. No exposed or fixed deployment was observed. No plaintext listener on a public interface: ss -tlnp (Linux) shows nothing bound to 0.0.0.0 or a public address on a plain HTTP port, except a listener whose only job is to redirect to HTTPS.
REASONED: HTTP redirect check; local marking review (October 2026, Bash 5.3.9) ran bash -n and ShellCheck 0.11.0 with exit 0 and no output; a curl stub printed the -sS -o /dev/null -w arguments and http://REPLACE_WITH_YOUR_HOST/ (exit 0). A live HTTP deployment stand-up opens a listener; the authoring host forbids that without an isolated network namespace, and none was available. Per README.sources.md entry 2 (RFC 9110, HTTP Semantics; curl manual), the exposed HTTP route serves without an HTTPS redirect; the fixed route returns a redirect status and HTTPS Location. No live response was observed. Where HTTP is offered, the redirect works: curl -sS -o /dev/null -w '%{http_code} %{redirect_url}\n' http://REPLACE_WITH_YOUR_HOST/ returns 301 or 308 (the preferred permanent redirects), or 302/307 where a framework issues them, always with a Location: https://... header.
REASONED: HTTPS certificate check; local marking review (October 2026, Bash 5.3.9) ran bash -n and ShellCheck 0.11.0 with exit 0 and no output; a curl stub printed the -sS -o /dev/null -w arguments and https://REPLACE_WITH_YOUR_HOST/ (exit 0). A live HTTPS deployment stand-up opens a listener; the authoring host forbids that without an isolated network namespace, and none was available. Per README.sources.md entry 3 (curl manual), an exposed invalid certificate makes verified curl fail, while a fixed trusted certificate lets curl succeed without -k. No certificate was tested. TLS works: curl -sS -o /dev/null -w '%{http_code}\n' https://REPLACE_WITH_YOUR_HOST/ succeeds without -k.
REASONED: TLS 1.1 refusal check; local marking review (October 2026, Bash 5.3.9, OpenSSL 3.5.5) ran bash -n and ShellCheck 0.11.0 with exit 0 and no output; a stub printed stub openssl args: s_client -connect REPLACE_WITH_YOUR_HOST:443 -tls1_1 (exit 0), while local openssl ciphers -s -tls1_1 exited 0 with only a newline, so that client cannot distinguish server refusal here. A live TLS deployment stand-up opens a listener; the authoring host forbids that without an isolated network namespace, and none was available. A client or scanner capable of offering TLS 1.1 and a live TLS 1.2 service control were also unavailable to this review. Per README.sources.md entry 4 (openssl-s_client; RFC 8996, Deprecating TLS 1.0 and TLS 1.1; OpenSSL config), an exposed TLS 1.1 server negotiates when a capable client offers it; a fixed server refuses that offer while a TLS 1.2 control succeeds. Neither state was observed. Old protocols are refused: openssl s_client -connect REPLACE_WITH_YOUR_HOST:443 -tls1_1 fails to negotiate (TLS 1.2 is the minimum everywhere in these guides). Confirm the refusal came from the server and not from your own client: a local OpenSSL build, or a MinProtocol setting in its configuration, can refuse TLS 1.1 before any offer is sent, which looks identical. Check that your client can still offer TLS 1.1 at all, or use an external scanner that does.
Authentication is enforced: an unauthenticated request to any non-public path returns 401, 403, or a login redirect, never data. Test the API paths as well as the home page.
No default credentials remain, and no secret (password, key, token, certificate private key) is committed to the repository. Scan before pushing, for example with gitleaks.
Where ACME is used, renewal is automated: sudo certbot renew --dry-run passes AND something is actually scheduled to run it. The dry run proves the command works, not that it will ever be invoked, so check the scheduler too: systemctl list-timers shows an active certbot timer with a next run, or the packaged cron entry is present. Servers that manage renewal themselves (Caddy, Traefik) need no timer; confirm a completed renewal in their logs instead.
Human-facing logins carry a second factor where the stack supports one; mfa.md lists the options, and the per-tool guides state what is viable.
Probe from outside the deployment network, from a second host: cloud-firewall and Docker-publishing mistakes only show from outside. Shodan or Censys can corroborate, but they report what a scanner last observed rather than what is listening now, so a port published since their last pass will not appear; treat them as a second opinion, never as a substitute for a live probe. See deployment-lifecycle.md.
Where login comes from an identity provider, an authenticated identity outside the allowed tenant, domain, group, or users is denied; test with such an account, not only an anonymous request.
Sources for these checks are listed in README.sources.md, numbered to match the items above.
Scope and currency
The guides use placeholders that you must replace. example.com and app.example.com stand in for a name, and 203.0.113.10 for an address, wherever the value is configuration or illustration. That is usually a wrong value that fails visibly, though not always: an unreplaced certificate SAN generates a perfectly valid certificate for the wrong address. Where leaving the placeholder in place would instead look like a passing check, the guides use a REPLACE_WITH_A_NAME form and the check itself rejects the unsubstituted value rather than trusting it to fail. The verification checklist above uses that second form for exactly that reason. Configuration syntax was checked against the vendor documentation cited in each guide as of September 2026; directives and dashboard menu locations change, so verify version-specific items against the current documentation for your installed version. Each guide lists its sources.
Scope: deployment exposure, including TLS, human and machine authentication, MFA, access restrictions, secrets, and inbound and outbound network access, from first deployment through teardown. General application security, including injection, deserialization, and business logic flaws, belongs to the OWASP resources linked throughout the guides. LLM-specific application risks such as prompt injection are covered by the OWASP Top 10 for LLM Applications. To propose a tool or guide, see CONTRIBUTING.md.
Licence
Everything in this repository (the guides, the configuration samples, and the site) is dedicated to the public domain under CC0 1.0 Universal. Copy and reuse it freely; no attribution is required. The one exception is the AIQT Guardrails material that .aiqt/PIN lists (the files vendored under .aiqt/ and tools/, and the AIQT sections adapted into CLAUDE.md and AGENTS.md), which is licensed under the Apache License 2.0 (see .aiqt/LICENSE and .aiqt/NOTICE).
About
Security, TLS, authentication, and other hardening setup guides written for AI development assistants: free and self-signed certificates, Cloudflare Zero Trust, and hardening steps for common servers, frameworks, and databases.