From 5cf7dc8c93b4c4fa0c2054deeecb366a3881b177 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sat, 14 Mar 2020 10:38:42 -0600 Subject: [PATCH] Update for beta 17 --- Caddyfile | 2 +- README.md | 4 +- src/docs/markdown/automatic-https.md | 68 ++++++++++++++++--- src/docs/markdown/caddyfile-tutorial.md | 7 +- src/docs/markdown/caddyfile/concepts.md | 11 ++- src/docs/markdown/caddyfile/directives/tls.md | 3 +- src/docs/markdown/caddyfile/options.md | 2 + src/docs/markdown/command-line.md | 57 +++++++++++++--- src/docs/markdown/conventions.md | 3 +- src/docs/markdown/quick-starts/caddyfile.md | 20 ++++-- src/docs/markdown/quick-starts/file-server.md | 26 +++---- .../markdown/quick-starts/reverse-proxy.md | 8 +-- src/includes/footer.html | 2 +- src/index.html | 2 + 14 files changed, 154 insertions(+), 61 deletions(-) diff --git a/Caddyfile b/Caddyfile index 573c2fa..9fa1df9 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,4 +1,4 @@ -:2015 +localhost root * src diff --git a/README.md b/README.md index da9bb14..cc2e741 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ This is the source of the Caddy website, [caddyserver.com](https://caddyserver.c 2. `cd website` 3. `caddy run` -You can then load [localhost:2015](http://localhost:2015) in your browser. +Your first time, you may be prompted for a password. This is so Caddy can serve the site over local HTTPS. + +You can then load [https://localhost](https://localhost) in your browser. diff --git a/src/docs/markdown/automatic-https.md b/src/docs/markdown/automatic-https.md index e2488c9..56c5432 100644 --- a/src/docs/markdown/automatic-https.md +++ b/src/docs/markdown/automatic-https.md @@ -18,10 +18,21 @@ Here's a 28-second video showing how it works: ## tl;dr -Here's what you need to know: +**Caddy serves all sites over HTTPS by default.** +- Caddy serves IP addresses and local/internal hostnames over HTTPS with locally-trusted ceritficates. Examples: `localhost`, `127.0.0.1`. +- Caddy serves public DNS names over HTTPS with certificates from [Let's Encrypt](https://letsencrypt.org). Examples: `example.com`, `sub.example.com`, `*.example.com`. - +Caddy keeps all certificates renewed, and redirects HTTP (default port 80) to HTTPS (default port 443) automatically. + +**For local HTTPS:** + +- Caddy may prompt for a password to install its root certificate into your trust store. This happens only once per root. +- Any client accessing the site without trusting the root cert will show security errors. + +**For public domain names:** + + - If your domain's A/AAAA records point to your server, - ports 80 and 443 are open externally, @@ -29,7 +40,7 @@ Here's what you need to know: - your `$HOME` folder is writeable and persistent, - and your domain name appears somewhere relevant in the config, -then your sites will probably be served over HTTPS automatically and without problems. You won't have to know or do anything else about it. It "just works" most of the time! +then sites will be served over HTTPS automatically and without problems. You won't have to know or do anything else about it. It should "just work"! @@ -49,7 +60,7 @@ Caddy implicitly activates automatic HTTPS when it knows a domain name (i.e. hos Any of the following will prevent automatic HTTPS from being activated, either in whole or in part: - [Explicitly disabling it](/docs/json/apps/http/servers/automatic_https/) -- Not providing any qualifying hostnames in the config +- Not providing any hostnames or IP addresses in the config - Listening exclusively on the HTTP port - Manually loading certificates (unless [this config property](/docs/json/apps/http/servers/automatic_https/ignore_loaded_certificates/) is true) @@ -58,7 +69,7 @@ Any of the following will prevent automatic HTTPS from being activated, either i When automatic HTTPS is activated, the following occurs: -- Certificates are obtained and renewed for [qualifying domain names](#hostname-requirements) +- Certificates are obtained and renewed for [all domain names](#hostname-requirements) - The default port (if any) is changed to the [HTTPS port](/docs/json/apps/http/https_port/) 443 - HTTP is redirected to HTTPS (this uses [HTTP port](/docs/json/apps/http/http_port/) 80) @@ -69,14 +80,49 @@ You can [customize or disable automatic HTTPS](/docs/json/apps/http/servers/auto ## Hostname requirements -A hostname qualifies for automatic HTTPS if it: +All hostnames (domain names and IP addresses) qualify for fully-managed certificates if they: + +- are non-empty +- consist only of alphanumerics, hyphens, dots, and wildcard (`*`) +- do not start or end with a dot ([RFC 1034](https://tools.ietf.org/html/rfc1034#section-3.5)) + +In addition, a hostname qualifies for a publicly-trusted certificate if it: -- is not empty - is not localhost - is not an IP address -- does not start or end with a dot ([RFC 1034](https://tools.ietf.org/html/rfc1034#section-3.5)) -- consists only of alphanumerics, hyphens, and dots - - with the exception of a single wildcard `*` as the left-most label (this requires the DNS challenge if using Let's Encrypt) +- has only a single wildcard `*` as the left-most label + + + +## Local HTTPS + +To serve non-public sites over HTTPS, Caddy generates its own certificate authority (CA) and uses it to sign certificates. The trust chain consists of a root and intermediate certificate. Leaf certificates are signed by the intermediate. + +Caddy's local CA is powered by [Smallstep libraries](https://smallstep.com/certificates/). + +Local HTTPS does not use ACME nor does it perform any DNS validation. It works only on the local machine and is trusted only where the CA's root certificate is installed. + +### CA Root + + + +The root's private key is uniquely generated using a cryptographically-secure pseudorandom source and persisted to storage with limited permissions. It is loaded into memory only to perform signing tasks, after which it leaves scope to be garbage-collected. + +Although Caddy can be configured to sign with the root directly (to support non-compliant clients), this is disabled by default, and the root key is only used to sign intermediates. + +The first time a root key is used, Caddy will try to install it into the system's local trust store(s). If it does not have permission to do so, it will prompt for a password. This behavior can be disabled in the configuration if it is not desired. + +After Caddy's root CA is installed, you will see it in your local trust store as "Caddy Local Authority" (unless you've configured a different name). You can uninstall it any time if you wish (the [`caddy untrust`](/docs/command-line#caddy-untrust) command makes this easy). + + +### CA Intermediates + +An intermediate certificate and key will also be generated, which will be used for signing leaf (individual site) certificates. + +Unlike the root certificate, intermediate certificates have a much shorter lifetime and will automatically be renewed as needed. + + + ## Testing @@ -174,4 +220,4 @@ Before attempting any ACME transactions, Caddy will test the configured storage Caddy can obtain and manage wildcard certificates when it is configured to serve a site with a qualifying wildcard name. A site name qualifies for a wildcard if only its left-most domain label is a wildcard. For example, `*.example.com` qualifies, but these do not: `sub.*.example.com`, `foo*.example.com`, `*bar.example.com`, and `*.*.example.com`. -To get a wildcard, you simply need to enable the [DNS challenge](#dns-challenge) and use a wildcard domain in your config. We recommend using wildcards only when you have so many subdomains that you would encounter CA rate limits trying to obtain certificates for them all. +To get a wildcard from Let's Encrypt, you simply need to enable the [DNS challenge](#dns-challenge) and use a wildcard domain in your config. We recommend using wildcards only when you have so many subdomains that you would encounter CA rate limits trying to obtain certificates for them all. diff --git a/src/docs/markdown/caddyfile-tutorial.md b/src/docs/markdown/caddyfile-tutorial.md index 2ccb669..7383c51 100644 --- a/src/docs/markdown/caddyfile-tutorial.md +++ b/src/docs/markdown/caddyfile-tutorial.md @@ -43,12 +43,11 @@ Save that and run Caddy:
caddy run
+The first time, you'll be asked for your password. This is so Caddy can serve your localhost site over HTTPS. -Open [localhost:2015](http://localhost:2015) in your browser and see your web server working! - -Why 2015? Caddy's default port is 2015. Since Caddy cannot activate [automatic HTTPS](/docs/automatic-https) with a hostname like "localhost", it leaves the port unchanged. +Open [localhost](https://localhost) in your browser and see your web server working, complete with HTTPS! Stop Caddy by pressing Ctrl+C in your terminal. @@ -80,7 +79,7 @@ Let's do something interesting with our file server: serve a templated page. Cre ``` -Save this as `caddy.html` in the current directory and load it in your browser: [http://localhost:2015/caddy.html](http://localhost:2015/caddy.html) +Save this as `caddy.html` in the current directory and load it in your browser: [https://localhost/caddy.html](https://localhost/caddy.html) The output is: diff --git a/src/docs/markdown/caddyfile/concepts.md b/src/docs/markdown/caddyfile/concepts.md index 7b948fd..fc8a18f 100644 --- a/src/docs/markdown/caddyfile/concepts.md +++ b/src/docs/markdown/caddyfile/concepts.md @@ -121,7 +121,7 @@ An address always appears at the top of the site block, and is usually the first These are examples of valid addresses: - `localhost` @@ -133,7 +133,7 @@ These are examples of valid addresses: - `[::1]:2015` - `example.com/foo/*` -From the address, Caddy can potentially infer the scheme, host, port, and path of your site. The default port is 2015 unless [automatic HTTPS](/docs/automatic-https#activation) is activated, which changes it to the HTTPS port. +From the address, Caddy can potentially infer the scheme, host, port, and path of your site. If you specify a hostname, only requests with a matching Host header will be honored. In other words, if the site address is `localhost`, then Caddy will not match requests to `127.0.0.1`. @@ -275,7 +275,12 @@ You can use any [Caddy placeholders](/docs/conventions#placeholders) in the Cadd | `{remote_port}` | `{http.request.remote.port}` | | `{scheme}` | `{http.request.scheme}` | | `{uri}` | `{http.request.uri}` | - +| `{tls_cipher}` | `{http.request.tls.cipher_suite}` | +| `{tls_version}` | `{http.request.tls.version}` | +| `{tls_client_fingerprint}` | `{http.request.tls.client.fingerprint}` | +| `{tls_client_issuer}` | `{http.request.tls.client.issuer}` | +| `{tls_client_serial}` | `{http.request.tls.client.serial}` | +| `{tls_client_subject}` | `{http.request.tls.client.subject}` | ## Snippets diff --git a/src/docs/markdown/caddyfile/directives/tls.md b/src/docs/markdown/caddyfile/directives/tls.md index 680a143..4a15850 100644 --- a/src/docs/markdown/caddyfile/directives/tls.md +++ b/src/docs/markdown/caddyfile/directives/tls.md @@ -14,7 +14,7 @@ Compatibility note: Due to its sensitive nature as a security protocol, delibera ## Syntax ``` -tls |[ ] { +tls [internal|] | [ ] { protocols [] ciphers curves @@ -25,6 +25,7 @@ tls |[ ] { } ``` +- **internal** means to use Caddy's internal, locally-trusted CA to produce certificates for this site. - **<email>** is the email address to use for the ACME account managing the site's certificates. - **<cert_file>** and **<key_file>** are the paths to the certificate and private key PEM files. Specifying just one is invalid; specifying both will disable automatic HTTPS. - **protocols** specifies the minimum and maximum protocol versions. Default min: `tls1.2`. Default max: `tls1.3` diff --git a/src/docs/markdown/caddyfile/options.md b/src/docs/markdown/caddyfile/options.md index 2c7bbd2..306c182 100644 --- a/src/docs/markdown/caddyfile/options.md +++ b/src/docs/markdown/caddyfile/options.md @@ -27,6 +27,7 @@ Possible options are: } experimental_http3 + default_sni acme_ca acme_ca_root email @@ -39,6 +40,7 @@ Possible options are: - **https_port** is the port for the server to use for HTTPS. For internal use only; does not change the HTTPS port for clients. Default: 443 - **order** sets or changes the standard order of HTTP handler directive(s). Can set directives to be `first` or `last`, or `before` or `after` another directive. - **storage** configures Caddy's storage mechanism. Default: `file_system` +- **default_sni** sets a default TLS ServerName for when clients do not use SNI in their ClientHello. - **experimental_http3** enables experimental draft HTTP/3 support. Note that HTTP/3 is not a finished spec and client support is extremely limited. This option will go away in the future. _This option is not subject to compatibility promises._ - **acme_ca** specifies the URL to the ACME CA's directory. It is strongly recommended to set this to Let's Encrypt's [staging endpoint](https://letsencrypt.org/docs/staging-environment/) for testing or development. Default: Let's Encrypt's production endpoint. - **acme_ca_root** specifies a PEM file that contains a trusted root certificate for ACME CA endpoints, if not in the system trust store. diff --git a/src/docs/markdown/command-line.md b/src/docs/markdown/command-line.md index 6bf8b40..0fef8b3 100644 --- a/src/docs/markdown/command-line.md +++ b/src/docs/markdown/command-line.md @@ -29,6 +29,9 @@ The ellipses `...` indicates a continuation, i.e. one or more parameters. - **[caddy file-server](#caddy-file-server)** A simple but production-ready file server +- **[caddy fmt](#caddy-fmt)** + Formats a Caddyfile + - **[caddy hash-password](#caddy-hash-password)** Hashes a password and outputs base64 @@ -53,6 +56,9 @@ The ellipses `...` indicates a continuation, i.e. one or more parameters. - **[caddy stop](#caddy-stop)** Stops the running Caddy process +- **[caddy untrust](#caddy-untrust)** + Untrusts a certificate from local trust store(s) + - **[caddy validate](#caddy-validate)** Tests whether a config file is valid @@ -72,7 +78,7 @@ The ellipses `...` indicates a continuation, i.e. one or more parameters. [--pretty] [--validate] -Adapts a configuration to Caddy's native JSON config structure and writes the output to stdout, along with any warnings to stderr. +Adapts a configuration to Caddy's native JSON config structure and writes the output to stdout, along with any warnings to stderr, then exits. `--config` is the path to the config file. If blank, will default to `Caddyfile` in current directory if it exists; otherwise, this flag is required. @@ -132,9 +138,9 @@ Spins up a simple but production-ready static file server. `--root` specifies the root file path. Default is the current working directory. -`--listen` accepts a listener address. Default is `:2015`, unless `--domain` specifies a name that qualifies for HTTPS, then `:443` will be the default. +`--listen` accepts a listener address. Default is `:80`, unless `--domain` is used, then `:443` will be the default. -`--domain` will only serve files through that domain name, and Caddy will attempt to serve it over HTTPS if it qualifies for a certificate (i.e. is a public domain name), so make sure its DNS is configured properly first. If the name qualifies for a certificate, the default port will be changed to 443. +`--domain` will only serve files through that hostname, and Caddy will attempt to serve it over HTTPS, so make sure any public DNS is configured properly first if it's a public domain name. The default port will be changed to 443. `--browse` will enable directory listings if a directory without an index file is requested. @@ -142,6 +148,21 @@ This command disables the admin API, making it easier to run multiple instances + +### `caddy fmt` + +
caddy fmt [<path>]
+	[--write]
+ +Formats or prettifies a Caddyfile, then exits. The result is printed to stdout unless `--write` is used. + +`` specifies the path to the Caddyfile. If omitted, a file named Caddyfile in the current directory is assumed instead. + +`--write` causes the result to be written to the input file instead of being printed to the terminal. + + + + ### `caddy hash-password`
caddy hash-password
@@ -149,7 +170,7 @@ This command disables the admin API, making it easier to run multiple instances
 	[--algorithm <name>]
 	[--salt <string>]
-Hashes a password and writes the output to stdout in base64 encoding. +Hashes a password and writes the output to stdout in base64 encoding, then exits. `--plaintext` is the plaintext form of the password. @@ -164,7 +185,7 @@ Hashes a password and writes the output to stdout in base64 encoding.
caddy help [<command>]
-Prints CLI help text, optionally for a specific subcommand. +Prints CLI help text, optionally for a specific subcommand, then exits. @@ -173,7 +194,7 @@ Prints CLI help text, optionally for a specific subcommand.
caddy list-modules
 	[--versions]
-Prints the Caddy modules that are installed, optionally with version information from their associated Go modules. +Prints the Caddy modules that are installed, optionally with version information from their associated Go modules, then exits. NOTE: Due to [a bug in Go](https://github.com/golang/go/issues/29228), version information is only available if Caddy is built as a dependency and not as the main module. TODO: Link to docs that explain how to build Caddy with version info @@ -261,21 +282,37 @@ If you want to stop the current configuration but do not want to exit the proces +### `caddy untrust` + +
caddy untrust
+	[--ca <id>]
+	[--cert <path>]
+ +Untrusts a root certificate from the local trust store(s). Intended for development environments only. Specify either the `--ca` or `--cert` flags, but not both. If neither are specified, Caddy's default CA (`local`). + +`--ca` specifies the ID of the Caddy CA to untrust. The default CA's ID is `local`. + +`--cert` specifies the path to the PEM-encoded certificate file to uninstall. + + + + + ### `caddy validate`
caddy validate
 	[--config <path>]
 	[--adapter <name>]
-Validates a configuration file. This command deserializes the config, then loads and provisions all of its modules as if to start the config, but the config is not actually started. This exposes errors in a configuration that arise during loading or provisioning phases and is a stronger error check than merely serializing a config as JSON. +Validates a configuration file, then exits. This command deserializes the config, then loads and provisions all of its modules as if to start the config, but the config is not actually started. This exposes errors in a configuration that arise during loading or provisioning phases and is a stronger error check than merely serializing a config as JSON. -`--config` is the config file to validate. +`--config` is the config file to validate. Default is the `Caddyfile` in the current directory, if any. -`--adapter` is the name of the config adapter to use, if the config file is not in Caddy's native JSON format. +`--adapter` is the name of the config adapter to use, if the config file is not in Caddy's native JSON format. If the config file starts with `Caddyfile`, the `caddyfile` adapter is used by default. ### `caddy version`
caddy version
-Prints the version. +Prints the version and exits. diff --git a/src/docs/markdown/conventions.md b/src/docs/markdown/conventions.md index 1ac2b54..8948f80 100644 --- a/src/docs/markdown/conventions.md +++ b/src/docs/markdown/conventions.md @@ -56,7 +56,7 @@ unix//path/to/socket Caddy's configuration supports the use of _placeholders_ (variables). Using placeholders is a simple way to inject dynamic values into a static configuration. -Placeholders are bounded on either side by curly braces `{ }` and contain the variable name inside, for example: `{foo.bar}`. Variable names are typically namespaced with dots to avoid collisions across modules. +Placeholders are bounded on either side by curly braces `{ }` and contain the variable name inside, for example: `{foo.bar}`. Placeholder braces can be escaped, `\{like so\}`. Variable names are typically namespaced with dots to avoid collisions across modules. Which placeholders are available depends on the context. Not all placeholders are available in all parts of the config. For example, [the HTTP app sets placeholders](/docs/json/apps/http/) that are only available in areas of the config related to handling HTTP requests. @@ -70,6 +70,7 @@ Placeholder | Description `{system.os}` | The system's OS `{system.arch}` | The system's architecture `{time.now.common_log}` | The current timestamp in Common Log Format +`{time.now.year}` | The current year in YYYY format Not all config fields support placeholders, but most do where you would expect it. diff --git a/src/docs/markdown/quick-starts/caddyfile.md b/src/docs/markdown/quick-starts/caddyfile.md index 28faa1b..3394f6a 100644 --- a/src/docs/markdown/quick-starts/caddyfile.md +++ b/src/docs/markdown/quick-starts/caddyfile.md @@ -24,9 +24,15 @@ Save this and run Caddy from the same folder that contains your Caddyfile:
caddy start
-Either open your browser to [localhost:2015](http://localhost:2015) or `curl` it: + -
curl localhost:2015
+You will probably be asked for your password, because Caddy will serve all sites -- even local ones -- over HTTPS. (The password prompt should only happen the first time!)
+
+Either open your browser to [localhost](http://localhost) or `curl` it:
+
+
curl https://localhost
 Hello, world!
You can define multiple sites in a Caddyfile by wrapping them in curly braces `{ }`. Change your Caddyfile to be: @@ -44,18 +50,18 @@ localhost:2016 { You can give Caddy the updated configuration two ways, either with the API directly:
curl localhost:2019/load \
-  -X POST \
-  -H "Content-Type: text/caddyfile" \
-  --data-binary @Caddyfile
+	-X POST \
+	-H "Content-Type: text/caddyfile" \
+	--data-binary @Caddyfile
 
or with the reload command, which does the same API request for you:
caddy reload
-Try out your new "goodbye" endpoint [in your browser](http://localhost:2016) or with `curl` to make sure it works: +Try out your new "goodbye" endpoint [in your browser](https://localhost:2016) or with `curl` to make sure it works: -
curl localhost:2016
+
curl https://localhost:2016
 Goodbye, world!
When you are done with Caddy, make sure to stop it: diff --git a/src/docs/markdown/quick-starts/file-server.md b/src/docs/markdown/quick-starts/file-server.md index ae330e5..33bbdbd 100644 --- a/src/docs/markdown/quick-starts/file-server.md +++ b/src/docs/markdown/quick-starts/file-server.md @@ -21,17 +21,17 @@ In your terminal, change to the root directory of your site and run:
caddy file-server
-The default address is :2015, so load [localhost:2015](http://localhost:2015) in your browser to see your site! +If you get a permission error, it probably means your OS does not allow you to bind to low ports -- so use a high port instead: + +
caddy file-server --listen :2015
+ +Then open [localhost](http://localhost) (or [localhost:2015](http://localhost:2015)) in your browser to see your site! If you don't have an index file but you want to display a file listing, use the `--browse` option:
caddy file-server --browse
-You can also listen on port 80 easily enough: - -
caddy file-server --listen :80
- -Or set use another folder as the site root: +You can use another folder as the site root:
caddy file-server --root ~/mysite
@@ -47,11 +47,13 @@ localhost file_server ``` +If you don't have permission to bind to low ports, replace `localhost` with `localhost:2015` (or some other high port). + Then, from the same directory, run:
caddy run
-You can then load [localhost:2015](http://localhost:2015) to see your site! +You can then load [localhost](https://localhost) (or whatever the address in your config is) to see your site! The [`file_server` directive](/docs/caddyfile/directives/file_server) has more options for you to customize your site. Make sure to [reload](/docs/command-line#caddy-reload) Caddy (or stop and start it again) when you change the Caddyfile! @@ -63,15 +65,7 @@ localhost file_server browse ``` -You can also listen on port 80 easily enough: - -``` -:80 - -file_server -``` - -Or set use another folder as the site root: +You can also use another folder as the site root: ``` localhost diff --git a/src/docs/markdown/quick-starts/reverse-proxy.md b/src/docs/markdown/quick-starts/reverse-proxy.md index b27ba6a..f1e776f 100644 --- a/src/docs/markdown/quick-starts/reverse-proxy.md +++ b/src/docs/markdown/quick-starts/reverse-proxy.md @@ -24,13 +24,11 @@ In your terminal, run this command:
caddy reverse-proxy --to 127.0.0.1:9000
-Caddy's default address is :2015, so make a request to [localhost:2015](http://localhost:2015) to see it working! - -It's easy to change the proxy's address: +If you don't have permission to bind to low ports, you can proxy from a higher port:
caddy reverse-proxy --from :2016 --to 127.0.0.1:9000
-Now you can access the proxy at [localhost:2016](http://localhost:2016). +Then make a request to [localhost](https://localhost) (or whatever address you specified in `--from`) to see it working! @@ -48,7 +46,7 @@ Then, from the same directory, run:
caddy run
-You can then make a request to [localhost:2015](http://localhost:2015) to see it working! +You can then make a request to [https://localhost](https://localhost) to see it working! It's easy to change the proxy's address: diff --git a/src/includes/footer.html b/src/includes/footer.html index 1a8d035..573afd6 100644 --- a/src/includes/footer.html +++ b/src/includes/footer.html @@ -7,7 +7,7 @@ in partnership with Ardan Labs diff --git a/src/index.html b/src/index.html index eb072fe..8fd72ab 100644 --- a/src/index.html +++ b/src/index.html @@ -3,6 +3,8 @@ Caddy 2 - The Ultimate Server with Automatic HTTPS {{include "/includes/head.html"}} + +