mirror of
https://github.com/caddyserver/website.git
synced 2025-04-24 05:56:15 -04:00
docs: All-new design, along with many content updates in prep for RC1
This commit is contained in:
parent
fe58da0269
commit
3ecf039665
23 changed files with 562 additions and 435 deletions
|
@ -10,23 +10,20 @@
|
|||
{{include "/includes/docs-head.html"}}
|
||||
<meta property="og:title" content="{{$title}} - Caddy Documentation">
|
||||
<meta name="twitter:title" value="{{$title}} - Caddy Documentation">
|
||||
<link rel="stylesheet" href="/resources/css/chroma.css">
|
||||
</head>
|
||||
<body>
|
||||
{{include "/includes/docs-header.html"}}
|
||||
<main>
|
||||
{{include "/includes/docs-nav.html"}}
|
||||
<div class="article-container">
|
||||
<div class="beta-warning">
|
||||
<b>Caddy 2 is beta software.</b> It is ready for production, but some things will change between releases; check the <a href="https://github.com/caddyserver/caddy/releases">release notes</a> before upgrading.
|
||||
</div>
|
||||
<article class="centered">
|
||||
<div class="paper" id="paper1"></div>
|
||||
<div class="paper" id="paper2"></div>
|
||||
<article class="paper paper3">
|
||||
{{markdown $markdownFile.Body}}
|
||||
</article>
|
||||
</div>
|
||||
<div class="sidebar"></div>
|
||||
</main>
|
||||
|
||||
{{include "/includes/footer.html"}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
<main>
|
||||
{{include "/includes/docs-nav.html"}}
|
||||
<div class="article-container">
|
||||
<div class="breadcrumbs">
|
||||
<!--Populated by JS-->
|
||||
</div>
|
||||
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
|
||||
<article>
|
||||
<div class="paper" id="paper1"></div>
|
||||
<div class="paper" id="paper2"></div>
|
||||
<article class="paper paper3">
|
||||
<div class="breadcrumbs">
|
||||
<!--Populated by JS-->
|
||||
</div>
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@ To start the Caddy daemon, use the `run` subcommand:
|
|||
|
||||
<pre><code class="cmd bash">caddy run</code></pre>
|
||||
|
||||
<aside class="complete">✅ Run the daemon</aside>
|
||||
<aside class="complete">Run the daemon</aside>
|
||||
|
||||
This blocks forever, but what is it doing? At the moment... nothing. By default, Caddy's configuration ("config") is blank. We can verify this using the [admin API](/docs/api) in another terminal:
|
||||
|
||||
|
@ -38,7 +38,7 @@ We can make Caddy useful by giving it a config. One way to do this is by making
|
|||
To prepare our request, we need to make a config. Caddy's configuration is simply a [JSON document](/docs/json/) (or [anything that converts to JSON](/docs/config-adapters)).
|
||||
|
||||
<aside class="tip">
|
||||
Config files are not required. The configuration API can always be used without files, which is handy for automating things. This tutorial uses a file because it is convenient when editing by hand.
|
||||
Config files are not required. The configuration API can always be used without files, which is handy when automating things. This tutorial uses a file because it is more convenient for editing by hand.
|
||||
</aside>
|
||||
|
||||
Save this to a JSON file:
|
||||
|
@ -68,12 +68,12 @@ Save this to a JSON file:
|
|||
Then upload it:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
||||
<aside class="complete">✅ Give Caddy a config</aside>
|
||||
<aside class="complete">Give Caddy a config</aside>
|
||||
|
||||
We can verify that Caddy applied our new config with another GET request:
|
||||
|
||||
|
@ -84,7 +84,7 @@ Test that it works by going to [localhost:2015](http://localhost:2015) in your b
|
|||
<pre><code class="cmd"><span class="bash">curl localhost:2015</span>
|
||||
Hello, world!</code></pre>
|
||||
|
||||
<aside class="complete">✅ Test config</aside>
|
||||
<aside class="complete">Test config</aside>
|
||||
|
||||
If you see _Hello, world!_, then congrats -- it's working! It's always a good idea to make sure your config works as you expect, especially before deploying into production.
|
||||
|
||||
|
@ -100,12 +100,12 @@ Let's change our welcome message from "Hello world!" to something a little more
|
|||
Save the config file, then update Caddy's active configuration by running the same POST request again:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
||||
<aside class="complete">✅ Replace active config</aside>
|
||||
<aside class="complete">Replace active config</aside>
|
||||
|
||||
For good measure, verify that the config was updated:
|
||||
|
||||
|
@ -116,19 +116,19 @@ Test it by refreshing the page in your browser (or running `curl` again), and yo
|
|||
|
||||
## Config traversal
|
||||
|
||||
Instead of uploading the entire config file for a small change, let's use a powerful feature of Caddy's API to make the change without ever touching our config file.
|
||||
|
||||
<aside class="tip">
|
||||
Making little changes to production servers by replacing the entire config like we did above can be dangerous; it's like having root access to a file system. Caddy's API lets you limit the scope of your changes to guarantee that other parts of your config don't get changed accidentally.
|
||||
</aside>
|
||||
|
||||
Instead of uploading the entire config file for a small change, let's use a powerful feature of Caddy's API to make the change without ever touching our config file.
|
||||
|
||||
Using the request URI's path, we can traverse into the config structure and update only the message string (be sure to scroll right if clipped):
|
||||
|
||||
<pre><code class="cmd bash">curl \
|
||||
localhost:2019/config/apps/http/servers/example/routes/0/handle/0/body \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"Work smarter, not harder."'
|
||||
localhost:2019/config/apps/http/servers/example/routes/0/handle/0/body \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"Work smarter, not harder."'
|
||||
</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
|
@ -149,13 +149,13 @@ You should see:
|
|||
You can use the <a href="https://stedolan.github.io/jq/">jq command</a> to prettify JSON output: <b><code>curl ... | jq</code></b>
|
||||
</aside>
|
||||
|
||||
<aside class="complete">Traverse config</aside>
|
||||
|
||||
**Important note:** This should be obvious, but once you use the API to make a change that is not in your original config file, your config file becomes obsolete. There are a few ways to handle this:
|
||||
|
||||
- Use the `--resume` of the [caddy run](/docs/command-line#caddy-run) command to use the last active config.
|
||||
- [Export Caddy's new configuration](/docs/api#get-configpath) with a subsequent GET request.
|
||||
- Don't mix the use of config files with changes via the API; have one source of truth.
|
||||
|
||||
<aside class="complete">✅ Traverse config</aside>
|
||||
- [Export Caddy's new configuration](/docs/api#get-configpath) with a subsequent GET request (less recommended than the first two options).
|
||||
|
||||
|
||||
|
||||
|
@ -166,10 +166,10 @@ Config traversal is certainly useful, but the paths are little long, don't you t
|
|||
We can give our handler object an [`@id` tag](/docs/api#using-id-in-json) to make it easier to access:
|
||||
|
||||
<pre><code class="cmd bash">curl \
|
||||
localhost:2019/config/apps/http/servers/example/routes/0/handle/0/@id \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"msg"'
|
||||
localhost:2019/config/apps/http/servers/example/routes/0/handle/0/@id \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"msg"'
|
||||
</code></pre>
|
||||
|
||||
This adds a property to our handler object: `"@id": "msg"`, so it now looks like this:
|
||||
|
@ -193,16 +193,16 @@ We can then access it directly:
|
|||
And now we can change the message with a shorter path:
|
||||
|
||||
<pre><code class="cmd bash">curl \
|
||||
localhost:2019/id/msg/body \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"Some shortcuts are good."'
|
||||
localhost:2019/id/msg/body \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"Some shortcuts are good."'
|
||||
</code></pre>
|
||||
|
||||
And check it again:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/id/msg/body</code></pre>
|
||||
|
||||
<aside class="complete">✅ Use <code>@id</code> tags</aside>
|
||||
<aside class="complete">Use <code>@id</code> tags</aside>
|
||||
|
||||
|
||||
|
|
|
@ -6,17 +6,17 @@ title: "Automatic HTTPS"
|
|||
|
||||
**Caddy is the first and only web server to use HTTPS automatically _and by default_.**
|
||||
|
||||
<aside class="tip">Caddy innovated automatic HTTPS technology; we've been doing this since the first day it was possible in 2015. Caddy's HTTPS automation logic is the most mature and robust in the world.</aside>
|
||||
|
||||
Automatic HTTPS provisions TLS certificates for all your sites and keeps them renewed. It also redirects HTTP to HTTPS for you! Caddy uses safe and modern defaults -- no downtime or extra configuration required.
|
||||
|
||||
<aside class="tip">Caddy innovated automatic HTTPS technology; we've been doing this since the first day it was possible in 2015. Caddy's HTTPS automation logic is the most mature and robust in the world.</aside>
|
||||
|
||||
Here's a 28-second video showing how it works:
|
||||
|
||||
<iframe width="100%" height="480" src="https://www.youtube-nocookie.com/embed/nk4EWHvvZtI?rel=0" frameborder="0" allowfullscreen=""></iframe>
|
||||
|
||||
|
||||
|
||||
## tl;dr
|
||||
## Overview
|
||||
|
||||
**Caddy serves all sites over HTTPS by default.**
|
||||
|
||||
|
@ -32,7 +32,8 @@ Caddy keeps all certificates renewed, and redirects HTTP (default port 80) to HT
|
|||
|
||||
**For public domain names:**
|
||||
|
||||
<aside class="tip">These are common requirements for any basic production website, not just Caddy. The main thing is to set your DNS records properly <b>before</b> running Caddy and to make sure Caddy can store certificates on disk.</aside>
|
||||
<aside class="tip">These are common requirements for any basic production website, not just Caddy. The main difference is to set your DNS records properly <b>before</b> running Caddy.</aside>
|
||||
|
||||
|
||||
- If your domain's A/AAAA records point to your server,
|
||||
- ports 80 and 443 are open externally,
|
||||
|
@ -42,8 +43,6 @@ Caddy keeps all certificates renewed, and redirects HTTP (default port 80) to HT
|
|||
|
||||
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"!
|
||||
|
||||
<aside class="warning">Public CAs like Let's Encrypt enforce rate limits. If your DNS, network, or server is not properly configured, you could easily hit rate limits. The rest of this page describes how to avoid that.</aside>
|
||||
|
||||
If you are still testing your setup, however, please read on or you risk being rate limited by your CA. The rest of this page goes over the details for advanced use cases and troubleshooting purposes.
|
||||
|
||||
|
||||
|
@ -52,9 +51,9 @@ If you are still testing your setup, however, please read on or you risk being r
|
|||
|
||||
Caddy implicitly activates automatic HTTPS when it knows a domain name (i.e. hostname) it is serving. Depending on how you run or configure Caddy, there are various ways to tell Caddy which domain names to use:
|
||||
|
||||
- The [Caddyfile](/docs/caddyfile/concepts#addresses)
|
||||
- A [host matcher](/docs/json/apps/http/servers/routes/match/host/) in a route
|
||||
- Command line flags like [--domain](/command-line#caddy-file-server) or [--from](/docs/command-line#caddy-reverse-proxy)
|
||||
- A [site address](/docs/caddyfile/concepts#addresses) in the [Caddyfile](/docs/caddyfile)
|
||||
- A [host matcher](/docs/json/apps/http/servers/routes/match/host/) in a [route](/docs/modules/http#servers/routes)
|
||||
- Command line flags like [--domain](/docs/command-line#caddy-file-server) or [--from](/docs/command-line#caddy-reverse-proxy)
|
||||
- The [automate](/docs/json/apps/tls/certificates/automate/) certificate loader
|
||||
|
||||
Any of the following will prevent automatic HTTPS from being activated, either in whole or in part:
|
||||
|
@ -70,8 +69,8 @@ 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 [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)
|
||||
- The default port (if any) is changed to the [HTTPS port](/docs/modules/http#https_port) 443
|
||||
- HTTP is redirected to HTTPS (this uses [HTTP port](/docs/modules/http#http_port) 80)
|
||||
|
||||
Automatic HTTPS never overrides explicit configuration.
|
||||
|
||||
|
@ -86,11 +85,11 @@ All hostnames (domain names and IP addresses) qualify for fully-managed certific
|
|||
- 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:
|
||||
In addition, hostnams qualify for publicly-trusted certificates if they:
|
||||
|
||||
- is not localhost
|
||||
- is not an IP address
|
||||
- has only a single wildcard `*` as the left-most label
|
||||
- are not localhost
|
||||
- are not an IP address
|
||||
- have only a single wildcard `*` as the left-most label
|
||||
|
||||
|
||||
|
||||
|
@ -104,14 +103,14 @@ Local HTTPS does not use ACME nor does it perform any DNS validation. It works o
|
|||
|
||||
### CA Root
|
||||
|
||||
<aside class="tip">It is safe to trust Caddy's root certificate on your own machine as long as your computer is not compromised and your unique root key is not leaked.</aside>
|
||||
|
||||
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.
|
||||
|
||||
<aside class="tip">It is safe to trust Caddy's root certificate on your own machine as long as your computer is not compromised and your unique root key is not leaked.</aside>
|
||||
|
||||
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).
|
||||
|
||||
|
||||
|
@ -127,7 +126,7 @@ Unlike the root certificate, intermediate certificates have a much shorter lifet
|
|||
|
||||
## Testing
|
||||
|
||||
To test or experiment with your Caddy configuration, make sure you [change the ACME endpoint](/docs/json/apps/tls/automation/policies/management/acme/ca/) to a staging or development URL, otherwise you are likely to hit rate limits which can block your access to HTTPS for up to a week, depending on which rate limit you hit.
|
||||
To test or experiment with your Caddy configuration, make sure you [change the ACME endpoint](/docs/modules/tls.issuance.acme#ca) to a staging or development URL, otherwise you are likely to hit rate limits which can block your access to HTTPS for up to a week, depending on which rate limit you hit.
|
||||
|
||||
Caddy's default CA is [Let's Encrypt](https://letsencrypt.org/), which has a [staging endpoint](https://letsencrypt.org/docs/staging-environment/) that is not subject to the same [rate limits](https://letsencrypt.org/docs/rate-limits/):
|
||||
|
||||
|
@ -199,6 +198,8 @@ Here's what happens if there's an error obtaining or renewing a certificate:
|
|||
- Maximum of 1 day between attempts
|
||||
- For up to 30 days
|
||||
|
||||
During retries with Let's Encrypt, Caddy switches to their [staging environment](https://letsencrypt.org/docs/staging-environment/) to avoid rate limit concerns. This isn't a perfect strategy, but in general it's helpful.
|
||||
|
||||
ACME challenges take at least a few seconds, and internal rate limiting helps mitigate accidental abuse. Caddy uses internal rate limiting in addition to what you or the CA configure so that you can hand Caddy a platter with a million domain names and it will gradually -- but as fast as it can -- obtain certificates for all of them.
|
||||
|
||||
Caddy's internal rate limit is currently 10 attempts per ACME account per minute.
|
||||
|
|
|
@ -39,17 +39,19 @@ localhost
|
|||
respond "Hello, world!"
|
||||
```
|
||||
|
||||
Save that and run Caddy:
|
||||
Save that and run Caddy (since this is a training tutorial, we'll use the `--watch` flag so changes to our Caddyfile are applied automatically):
|
||||
|
||||
<pre><code class="cmd bash">caddy run</code></pre>
|
||||
<pre><code class="cmd bash">caddy run --watch</code></pre>
|
||||
|
||||
The first time, you'll be asked for your password. This is so Caddy can serve your localhost site over HTTPS.
|
||||
The first time, you'll be asked for your password. This is so Caddy can serve your site over HTTPS.
|
||||
|
||||
<aside class="complete">✅ First site</aside>
|
||||
<aside class="tip">Caddy serves all sites over HTTPS by default as long as a host or IP is part of the site's address. <a href="/docs/automatic-https">Automatic HTTPS</a> can be disabled by prefixing the address with <code>http://</code> explicitly.</aside>
|
||||
|
||||
<aside class="complete">First site</aside>
|
||||
|
||||
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.
|
||||
<aside class="tip">You might need to restart your browser if you get a certificate error the first time.</aside>
|
||||
|
||||
That's not particularly exciting, so let's change our static response to a [file server](/docs/caddyfile/directives/file_server) with directory listings enabled:
|
||||
|
||||
|
@ -59,9 +61,9 @@ localhost
|
|||
file_server browse
|
||||
```
|
||||
|
||||
Save your Caddyfile and run Caddy again. Then refresh your browser tab. You should either see a list of files or an HTML page if there is an index file in the current directory.
|
||||
Save your Caddyfile, then refresh your browser tab. You should either see a list of files or an HTML page if there is an index file in the current directory.
|
||||
|
||||
<aside class="complete">✅ Static file server</aside>
|
||||
<aside class="complete">Static file server</aside>
|
||||
|
||||
## Adding functionality
|
||||
|
||||
|
@ -96,9 +98,7 @@ templates
|
|||
file_server browse
|
||||
```
|
||||
|
||||
<aside class="tip">You can also reload Caddy's config without downtime (i.e. without stopping it and starting it again) using the <a href="/docs/command-line#caddy-reload"><code>caddy reload</code></a> command.</aside>
|
||||
|
||||
Save that, then restart Caddy, then reload the browser tab. You should see:
|
||||
Save that, then reload the browser tab. You should see:
|
||||
|
||||
```
|
||||
Page loaded at: {{now | date "Mon Jan 2 15:04:05 MST 2006"}}
|
||||
|
@ -106,9 +106,9 @@ Page loaded at: {{now | date "Mon Jan 2 15:04:05 MST 2006"}}
|
|||
|
||||
With Caddy's [templates module](/docs/modules/http.handlers.templates), you can do a lot of useful things with static files, such as including other HTML files, making sub-requests, setting response headers, working with data structures, and more!
|
||||
|
||||
<aside class="complete">✅ Templates</aside>
|
||||
<aside class="complete">Templates</aside>
|
||||
|
||||
It's good practice to compress responses with a quick and modern compression algorithm. Let's enable compression using Gzip and Zstandard using the [`encode`](/docs/caddyfile/directives/encode) directive:
|
||||
It's good practice to compress responses with a quick and modern compression algorithm. Let's enable Gzip and Zstandard support using the [`encode`](/docs/caddyfile/directives/encode) directive:
|
||||
|
||||
```
|
||||
localhost
|
||||
|
@ -118,7 +118,10 @@ templates
|
|||
file_server browse
|
||||
```
|
||||
|
||||
<aside class="complete">✅ Compression</aside>
|
||||
<aside class="tip">Browsers don't support Zstandard encodings yet. Hopefully soon!</aside>
|
||||
|
||||
|
||||
<aside class="complete">Compression</aside>
|
||||
|
||||
That's the basic process for getting a semi-advanced, production-ready site up and running!
|
||||
|
||||
|
@ -178,7 +181,7 @@ For multiple sites which share the same configuration, you can add more addresse
|
|||
|
||||
You can then define as many different sites as you want, as long as each address is unique.
|
||||
|
||||
<aside class="complete">✅ Multiple sites</aside>
|
||||
<aside class="complete">Multiple sites</aside>
|
||||
|
||||
|
||||
## Matchers
|
||||
|
@ -194,7 +197,7 @@ file_server
|
|||
reverse_proxy 127.0.0.1:9005
|
||||
```
|
||||
|
||||
In practice, we may want to use the reverse proxy only for API requests, i.e. requests with a base path of `/api/`. This is easy to do, by adding a matcher token:
|
||||
In practice, we may want to use the reverse proxy only for API requests, i.e. requests with a base path of `/api/`. This is easy to do by adding a [matcher token](/docs/caddyfile/matchers#syntax):
|
||||
|
||||
```
|
||||
localhost
|
||||
|
@ -207,9 +210,9 @@ There; now the reverse proxy will be prioritized for all requests starting with
|
|||
|
||||
The `/api/*` token we just added is called a **matcher token**. You can tell it's a matcher token because it starts with a forward slash `/` and it appears right after the directive (but you can always look it up in the [directive's docs](/docs/caddyfile/directives) to be sure).
|
||||
|
||||
Matchers are actually really powerful. You can name matchers and use them like `@name` to match on more than just the request path! Take a moment to [learn more about matchers](/docs/caddyfile/matchers) before continuing!
|
||||
Matchers are really powerful. You can name matchers and use them like `@name` to match on more than just the request path! Take a moment to [learn more about matchers](/docs/caddyfile/matchers) before continuing!
|
||||
|
||||
<aside class="complete">✅ Matchers</aside>
|
||||
<aside class="complete">Matchers</aside>
|
||||
|
||||
## Environment variables
|
||||
|
||||
|
@ -237,7 +240,7 @@ file_server
|
|||
|
||||
You can use environment variables anywhere in the Caddyfile, for any number of tokens.
|
||||
|
||||
<aside class="complete">✅ Environment variables</aside>
|
||||
<aside class="complete">Environment variables</aside>
|
||||
|
||||
|
||||
## Comments
|
||||
|
@ -248,7 +251,7 @@ One last thing that you will find most helpful: if you want to remark or note an
|
|||
# this starts a comment
|
||||
```
|
||||
|
||||
<aside class="complete">✅ Comments</aside>
|
||||
<aside class="complete">Comments</aside>
|
||||
|
||||
## Further reading
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ respond [<matcher>] <status>|<body> [<status>] {
|
|||
|
||||
To clarify, the first non-matcher argument can be either a 3-digit status code or a response body string. If it is a body, the next argument can be the status code.
|
||||
|
||||
<aside class="tip">
|
||||
Responding with an error status code is different than returning an error in the handler chain, which invokes error handlers internally.
|
||||
</aside>
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
|
|
|
@ -249,10 +249,6 @@ This command disables the admin API, making it easier to run multiple instances
|
|||
[--resume]
|
||||
[--watch]</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
To change the active configuration while running in production, do not stop the server! That will result in downtime. (This should be obvious but you'd be surprised how many complaints we get about it.) Use the <a href="#caddy-reload">caddy reload</a> command instead.
|
||||
</aside>
|
||||
|
||||
Runs Caddy and blocks indefinitely; i.e. "daemon" mode.
|
||||
|
||||
`--config` specifies an initial config file to immediately load and use. If no config is specified, Caddy will run with a blank configuration and use default settings for the [admin API endpoints](/docs/api), which can be used to feed it new configuration. As a special case, if the current working directory has a file called "Caddyfile" and the `caddyfile` config adapter is plugged in (default), then that file will be loaded and used to configure Caddy, even without any command line flags.
|
||||
|
@ -265,6 +261,11 @@ Runs Caddy and blocks indefinitely; i.e. "daemon" mode.
|
|||
|
||||
`--watch` will watch the config file and automatically reload it after it changes. ⚠️ This feature is dangerous in production! Only use it in a local development environment.
|
||||
|
||||
<aside class="advice">
|
||||
Do not stop the server to change configuration while running in production! That will result in downtime. (This should be obvious but you'd be surprised how many complaints we get about it.) Use the <a href="#caddy-reload">caddy reload</a> command instead.
|
||||
</aside>
|
||||
|
||||
|
||||
|
||||
### `caddy start`
|
||||
|
||||
|
@ -286,7 +287,7 @@ Once started, you can use [`caddy stop`](#caddy-stop) or [the /stop API endpoint
|
|||
<pre><code class="cmd bash">caddy stop [--address <interface>]</code></pre>
|
||||
|
||||
<aside class="tip">
|
||||
Stopping (and restarting) the server is orthogonal to config changes. Do not use the stop command to change configuration in production, unless you want downtime. Use the <a href="#caddy-reload">caddy reload</a> command instead.
|
||||
Stopping (and restarting) the server is orthogonal to config changes. <b>Do not use the stop command to change configuration in production, unless you want downtime.</b> Use the <a href="#caddy-reload">caddy reload</a> command instead.
|
||||
</aside>
|
||||
|
||||
Gracefully stops the running Caddy process (other than the process of the stop command) and causes it to exit. It uses the [/stop endpoint](/docs/api#post-stop) of the admin API to perform a graceful shutdown.
|
||||
|
|
|
@ -9,10 +9,6 @@ The Caddy ecosystem adheres to a few conventions to make things consistent and i
|
|||
|
||||
## Network addresses
|
||||
|
||||
<aside class="tip">
|
||||
Caddy network addresses are not URLs. URLs couple the lower and higher layers of the <a href="https://en.wikipedia.org/wiki/OSI_model#Layer_architecture">OSI model</a>, but Caddy often uses network addresses independently of a specific application, so combining them would be problematic. In Caddy, network addresses refer precisely to resources that can be dialed or bound at L3-L5, but URLs combine L3-L7, which is too many. A network address requires a host+port and path to be mutually exclusive, but URLs do not. Network addresses sometimes support port ranges, but URLs do not.
|
||||
</aside>
|
||||
|
||||
When specifying a network address to dial or bind, Caddy accepts a string in the following format:
|
||||
|
||||
```
|
||||
|
@ -47,15 +43,19 @@ udp/localhost:9005
|
|||
unix//path/to/socket
|
||||
```
|
||||
|
||||
<aside class="tip">
|
||||
Caddy network addresses are not URLs. URLs couple the lower and higher layers of the <a href="https://en.wikipedia.org/wiki/OSI_model#Layer_architecture">OSI model</a>, but Caddy often uses network addresses independently of a specific application, so combining them would be problematic. In Caddy, network addresses refer precisely to resources that can be dialed or bound at L3-L5, but URLs combine L3-L7, which is too many. A network address requires a host+port and path to be mutually exclusive, but URLs do not. Network addresses sometimes support port ranges, but URLs do not.
|
||||
</aside>
|
||||
|
||||
|
||||
## Placeholders
|
||||
|
||||
Caddy's configuration supports the use of _placeholders_ (variables). Using placeholders is a simple way to inject dynamic values into a static configuration.
|
||||
|
||||
<aside class="tip">
|
||||
Placeholders are a similar idea to variables in other software. For example, <a href="https://nginx.org/en/docs/varindex.html">nginx has variables</a> like $uri and $document_root.
|
||||
</aside>
|
||||
|
||||
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}`. 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.
|
||||
|
@ -81,12 +81,12 @@ This section contains information about where to find various files. File and di
|
|||
|
||||
### Your config files
|
||||
|
||||
There is no single, conventional place for you to put your config files. Put them wherever makes the most sense to you.
|
||||
|
||||
<aside class="tip">
|
||||
The only exception to this might be a file named "Caddyfile" in the current working directory, which the caddy command tries for convenience if no other config file is specified.
|
||||
</aside>
|
||||
|
||||
There is no single, conventional place for you to put your config files. Put them wherever makes the most sense to you.
|
||||
|
||||
Distributions that ship with a default config file should document where this config file is at, even if it might be obvious to the package/distro maintainers.
|
||||
|
||||
|
||||
|
@ -98,10 +98,6 @@ If the `XDG_DATA_HOME` environment variable is set, it is `$XDG_DATA_HOME/caddy`
|
|||
|
||||
Otherwise, its path varies by platform, adhering to OS conventions:
|
||||
|
||||
<aside class="tip">
|
||||
All other OSes use the Linux/BSD directory path.
|
||||
</aside>
|
||||
|
||||
OS | Data directory path
|
||||
---|---------------------
|
||||
**Linux, BSD** | `$HOME/.local/share/caddy`
|
||||
|
@ -110,6 +106,8 @@ OS | Data directory path
|
|||
**Plan 9** | `$HOME/lib/caddy`
|
||||
**Android** | `$HOME/caddy` (or `/sdcard/caddy`)
|
||||
|
||||
All other OSes use the Linux/BSD directory path.
|
||||
|
||||
The data directory must not be treated like a cache. Its contents are not ephemeral or merely for the sake of performance. Caddy stores TLS certificates, private keys, OCSP staples, and other necessary information to the data directory. It should not be purged without an understanding of the implications.
|
||||
|
||||
It is crucial that this directory is persistent and writeable by Caddy.
|
||||
|
@ -117,21 +115,16 @@ It is crucial that this directory is persistent and writeable by Caddy.
|
|||
|
||||
### Configuration directory
|
||||
|
||||
This is where Caddy may store certain configuration to disk. Most notably, it persists the last active configuration (by default) to this folder for easy resumption later using [`caddy run --resume`](/docs/command-line#caddy-run).
|
||||
|
||||
<aside class="tip">
|
||||
The configuration directory is <i>not</i> where you need to store <a href="#your-config-files">your config files</a>. (Though, you are allowed to.)
|
||||
</aside>
|
||||
|
||||
<!-- **The configuration directory is _not_ where you need to store [your config files](#your-config-files).** (Though, you are allowed to.) -->
|
||||
|
||||
This is where Caddy may store certain configuration to disk. Most notably, it persists the last active configuration (by default) to this folder for easy resumption later using [`caddy run --resume`](/docs/command-line#caddy-run).
|
||||
|
||||
If the `XDG_CONFIG_HOME` environment variable is set, it is `$XDG_CONFIG_HOME/caddy`.
|
||||
|
||||
Otherwise, its path varies by platform, adhering to OS conventions:
|
||||
|
||||
<aside class="tip">
|
||||
All other OSes use the Linux/BSD directory path.
|
||||
</aside>
|
||||
|
||||
OS | Config directory path
|
||||
---|---------------------
|
||||
|
@ -140,6 +133,8 @@ OS | Config directory path
|
|||
**macOS** | `$HOME/Library/Application Support/Caddy`
|
||||
**Plan 9** | `$HOME/lib/caddy`
|
||||
|
||||
All other OSes use the Linux/BSD directory path.
|
||||
|
||||
It is crucial that this directory is persistent and writeable by Caddy.
|
||||
|
||||
|
||||
|
@ -161,4 +156,4 @@ Examples:
|
|||
- `1.5h`
|
||||
- `2h45m`
|
||||
|
||||
In the [JSON config](/docs/json/), duration values can also be integers which represents nanoseconds.
|
||||
In the [JSON config](/docs/json/), duration values can also be integers which represent nanoseconds.
|
|
@ -34,15 +34,17 @@ Oops; without a subcommand, the `caddy` command only displays help text. You can
|
|||
|
||||
To start Caddy as a daemon, use the `run` subcommand:
|
||||
|
||||
<aside class="complete">✅ Run the daemon</aside>
|
||||
<pre><code class="cmd bash">caddy run</code></pre>
|
||||
|
||||
<aside class="complete">Run the daemon</aside>
|
||||
|
||||
This blocks forever, but what is it doing? At the moment... nothing. By default, Caddy's configuration ("config") is blank. We can verify this using the [admin API](/docs/api) in another terminal:
|
||||
|
||||
<aside class="complete">✅ Try the API</aside>
|
||||
<pre><code class="cmd bash">curl localhost:2019/config/</code></pre>
|
||||
|
||||
We can make Caddy useful by giving it a config. This can be done many ways, but we'll start by making a POST request to the [/load](/docs/api#post-load) endpoint using `curl`.
|
||||
<aside class="complete">Try the API</aside>
|
||||
|
||||
We can make Caddy useful by giving it a config. This can be done many ways, but we'll start by making a POST request to the [/load](/docs/api#post-load) endpoint using `curl` in the next section.
|
||||
|
||||
|
||||
|
||||
|
@ -50,10 +52,6 @@ We can make Caddy useful by giving it a config. This can be done many ways, but
|
|||
|
||||
To prepare our request, we need to make a config. At its core, Caddy's configuration is simply a [JSON document](/docs/json/).
|
||||
|
||||
<aside class="tip">
|
||||
Config files are not required. The admin API can always be used without files, which is handy when automating.
|
||||
</aside>
|
||||
|
||||
Save this to a JSON file:
|
||||
|
||||
```json
|
||||
|
@ -78,15 +76,19 @@ Save this to a JSON file:
|
|||
}
|
||||
```
|
||||
|
||||
<aside class="tip">
|
||||
You do not have to use files for configuration. The <a href="/docs/api">admin API</a> can always be used without files, which is handy when automating.
|
||||
</aside>
|
||||
|
||||
Then upload it:
|
||||
|
||||
<pre><code class="cmd bash">curl localhost:2019/load \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json
|
||||
</code></pre>
|
||||
|
||||
<aside class="complete">✅ Give Caddy a config</aside>
|
||||
<aside class="complete">Give Caddy a config</aside>
|
||||
|
||||
We can verify that Caddy applied our new config with another GET request:
|
||||
|
||||
|
@ -97,10 +99,9 @@ Test that it works by going to [localhost:2015](http://localhost:2015) in your b
|
|||
<pre><code class="cmd"><span class="bash">curl localhost:2015</span>
|
||||
Hello, world!</code></pre>
|
||||
|
||||
<aside class="complete">✅ Test config</aside>
|
||||
|
||||
If you see _Hello, world!_, then congrats -- it's working! It's always a good idea to make sure your config works as you expect, especially before deploying into production.
|
||||
|
||||
<aside class="complete">Test config</aside>
|
||||
|
||||
|
||||
## Your first Caddyfile
|
||||
|
@ -115,10 +116,11 @@ Another way to configure Caddy is with the [**Caddyfile**](/docs/caddyfile). The
|
|||
respond "Hello, world!"
|
||||
```
|
||||
|
||||
<aside class="complete">✅ Make a Caddyfile</aside>
|
||||
|
||||
Save that to a file named `Caddyfile` (no extension) in the current directory.
|
||||
|
||||
<aside class="complete">Make a Caddyfile</aside>
|
||||
|
||||
Stop Caddy if it is already running (Ctrl+C), then run:
|
||||
|
||||
<pre><code class="cmd bash">caddy adapt</code></pre>
|
||||
|
@ -127,31 +129,29 @@ Or if you stored the Caddyfile somewhere else or named it something other than `
|
|||
|
||||
<pre><code class="cmd bash">caddy adapt --config /path/to/Caddyfile</code></pre>
|
||||
|
||||
<aside class="complete">✅ Use the config adapter</aside>
|
||||
|
||||
You will see JSON output! What happened here?
|
||||
|
||||
We just used a [_config adapter_](/docs/config-adapters) to convert our Caddyfile to Caddy's native JSON structure.
|
||||
|
||||
While we could take that output and make another API request, we can skip all those steps because the `caddy` command can do it for us.
|
||||
<aside class="complete">Use the config adapter</aside>
|
||||
|
||||
Since the Caddyfile is so common, if there is a file called Caddyfile in the current directory and no other config is specified, Caddy will load the Caddyfile, adapt it for us, and run it right away.
|
||||
While we could take that output and make another API request, we can skip all those steps because the `caddy` command can do it for us. If there is a file called Caddyfile in the current directory and no other config is specified, Caddy will load the Caddyfile, adapt it for us, and run it right away.
|
||||
|
||||
So now that there is a Caddyfile in the current folder, let's do `caddy run` again:
|
||||
Now that there is a Caddyfile in the current folder, let's do `caddy run` again:
|
||||
|
||||
<pre><code class="cmd bash">caddy run</code></pre>
|
||||
|
||||
Or if your Caddyfile is somewhere else (or named something else):
|
||||
Or if your Caddyfile is somewhere else:
|
||||
|
||||
<pre><code class="cmd bash">caddy run \
|
||||
--config /path/to/Caddyfile \
|
||||
--adapter caddyfile</code></pre>
|
||||
<pre><code class="cmd bash">caddy run --config /path/to/Caddyfile</code></pre>
|
||||
|
||||
(If it is called something else that doesn't start with "Caddyfile", you will need to specify `--adapter caddyfile`.)
|
||||
|
||||
You can now try loading your site again and you will see that it is working!
|
||||
|
||||
<aside class="complete">✅ Start with an initial config</aside>
|
||||
<aside class="complete">Start with an initial config</aside>
|
||||
|
||||
As you can see, we can start Caddy with an initial config several ways:
|
||||
As you can see, there are several ways you can start Caddy with an initial config:
|
||||
|
||||
- A file named Caddyfile in the current directory
|
||||
- The `--config` flag (optionally with the `--adapter` flag)
|
||||
|
@ -160,9 +160,9 @@ As you can see, we can start Caddy with an initial config several ways:
|
|||
|
||||
## JSON vs. Caddyfile
|
||||
|
||||
Now you know that the Caddyfile is just converted to JSON under the hood.
|
||||
Now you know that the Caddyfile is just converted to JSON for you.
|
||||
|
||||
The Caddyfile seems simpler than the JSON, but should you always use it? There are pros and cons to each approach. The answer depends on your requirements and use case.
|
||||
The Caddyfile seems easier than JSON, but should you always use it? There are pros and cons to each approach. The answer depends on your requirements and use case.
|
||||
|
||||
JSON | Caddyfile
|
||||
-----|----------
|
||||
|
@ -182,15 +182,15 @@ Kind of boring | Kind of fun
|
|||
|
||||
You will need to decide which is best for your use case.
|
||||
|
||||
<aside class="complete">✅ Compare JSON and Caddyfile</aside>
|
||||
It is important to note that both JSON and the Caddyfile (and [any other supported config adapter](/docs/config-adapters)) can be used with [Caddy's API](/docs/api). However, you get the full range of Caddy's functionality and API features if you use JSON. If using a config adapter, the only way to load or change the config with the API is the [/load endpoint](/docs/api#post-load).
|
||||
|
||||
It is important to note that both JSON and the Caddyfile (and [any other supported config adapter](/docs/config-adapters)) can be used with Caddy's API. However, you get the full range of Caddy's functionality and API features if you use JSON. If using a config adapter, the only way to load or change the config with the API is the [/load endpoint](/docs/api#post-load).
|
||||
<aside class="complete">Compare JSON and Caddyfile</aside>
|
||||
|
||||
|
||||
## API vs. Config files
|
||||
|
||||
<aside class="tip">
|
||||
Under the hood, even config files go through Caddy's API endpoints; but the `caddy` command wraps the API calls up for you.
|
||||
Under the hood, even config files go through Caddy's API endpoints; the <code>caddy</code> command just wraps up those API calls for you.
|
||||
</aside>
|
||||
|
||||
You will also want to decide whether your workflow is API-based or CLI-based. (You _can_ use both the API and config files on the same server, but we don't recommend it: best to have one source of truth.)
|
||||
|
@ -204,22 +204,22 @@ Really fun | Also fun
|
|||
**Learn more: [API tutorial](/docs/api-tutorial)** | **Learn more: [Caddyfile tutorial](/docs/caddyfile-tutorial)**
|
||||
|
||||
<aside class="tip">
|
||||
Manually managing a server's configuration with the API is actually totally doable with proper tools, for example: a REST client GUI application.
|
||||
Manually managing a server's configuration with the API is totally doable with proper tools, for example: any REST client application.
|
||||
</aside>
|
||||
|
||||
The choice of API or config file workflow is orthogonal to the use of config adapters: you can use JSON but store it in a file and use the command line interface; conversely, you can also use the Caddyfile (e.g. from a template) with the API.
|
||||
The choice of API or config file workflow is orthogonal to the use of config adapters: you can use JSON but store it in a file and use the command line interface; conversely, you can also use the Caddyfile with the API.
|
||||
|
||||
But most people will use JSON+API or Caddyfile+CLI combinations.
|
||||
|
||||
As you can see, Caddy is well-suited for a wide variety of use cases and deployments!
|
||||
|
||||
<aside class="complete">✅ Compare API and config files</aside>
|
||||
<aside class="complete">Compare API and config files</aside>
|
||||
|
||||
|
||||
|
||||
## Start, stop, run
|
||||
|
||||
Since Caddy is a server, it runs indefinitely. That means your terminal won't unblock (can't be used) after you execute `caddy run` until the process is terminated (usually Ctrl+C).
|
||||
Since Caddy is a server, it runs indefinitely. That means your terminal won't unblock after you execute `caddy run` until the process is terminated (usually with Ctrl+C).
|
||||
|
||||
Although `caddy run` is the most common and is usually recommended (especially when making a system service!), you can alternatively use `caddy start` to start Caddy and have it run in the background:
|
||||
|
||||
|
@ -233,27 +233,31 @@ You will then have to stop the process yourself, since Ctrl+C won't stop it for
|
|||
|
||||
Or use [the /stop endpoint](/docs/api#post-stop) of the API.
|
||||
|
||||
<aside class="complete">✅ Run in the background</aside>
|
||||
<aside class="complete">Run in the background</aside>
|
||||
|
||||
|
||||
## Reloading config
|
||||
|
||||
Whether using the API or command line, your server can perform zero-downtime config reloads or changes.
|
||||
Your server can perform zero-downtime config reloads/changes.
|
||||
|
||||
All [API endpoints](/docs/api) that load or change config are already graceful with zero downtime.
|
||||
All [API endpoints](/docs/api) that load or change config are graceful with zero downtime.
|
||||
|
||||
When using config files with the CLI, however, it may be tempting to use Ctrl+C to stop your server and restart it again to pick up the new configuration. This is sometimes fine in local dev environments, but is a bad idea on a production server.
|
||||
|
||||
Instead, use the [`caddy reload`](/docs/command-line#caddy-reload) command:
|
||||
When using the command line, however, it may be tempting to use Ctrl+C to stop your server and then restart it again to pick up the new configuration. Don't do this: stopping and starting the server is orthogonal to config changes, and will result in downtime.
|
||||
|
||||
<aside class="tip">
|
||||
Technically, the new config is started before the old config is stopped, so for a brief time, both configs are running! If the new config fails, the old one is simply not stopped, rather than being "rolled back".
|
||||
Stopping your server will cause the server to go down.
|
||||
</aside>
|
||||
|
||||
Instead, use the [`caddy reload`](/docs/command-line#caddy-reload) command for a graceful config change:
|
||||
|
||||
<pre><code class="cmd bash">caddy reload</code></pre>
|
||||
|
||||
This actually just uses the API under the hood, but it will load and (if necessary) adapt your config file to JSON, then gracefully replace the active configuration without downtime.
|
||||
This actually just uses the API under the hood. It will load and, if necessary, adapt your config file to JSON, then gracefully replace the active configuration without downtime.
|
||||
|
||||
If there are any errors loading the new config, Caddy rolls back to the last working config.
|
||||
|
||||
<aside class="complete">✅ Zero-downtime config reload</aside>
|
||||
<aside class="tip">
|
||||
Technically, the new config is started before the old config is stopped, so for a brief time, both configs are running! If the new config fails, it aborts with an error, while the old one is simply not stopped.
|
||||
</aside>
|
||||
|
||||
<aside class="complete">Zero-downtime config reload</aside>
|
|
@ -13,6 +13,6 @@ It is **highly recommended** that you follow-up by reading other tutorials and r
|
|||
|
||||
- #### [Using the API](/docs/quick-starts/api)
|
||||
- #### [Using a Caddyfile](/docs/quick-starts/caddyfile)
|
||||
- #### [File server](/docs/quick-starts/file-server)
|
||||
- #### [Static file server](/docs/quick-starts/static-files)
|
||||
- #### [Reverse proxy](/docs/quick-starts/reverse-proxy)
|
||||
- #### [HTTPS](/docs/quick-starts/https)
|
||||
|
|
|
@ -6,6 +6,10 @@ title: HTTPS quick-start
|
|||
|
||||
This guide will show you how to get up and running with [fully-managed HTTPS](/docs/automatic-https) in no time.
|
||||
|
||||
<aside class="tip">
|
||||
Caddy uses HTTPS for all sites by default, as long as a host name is provided in the config. This tutorial assumes you want to get a publicly-trusted site up over HTTPS, which requires a public domain name (i.e. not "localhost") and external ports.
|
||||
</aside>
|
||||
|
||||
**Prerequisites:**
|
||||
- Basic terminal / command line skills
|
||||
- Basic understanding of DNS
|
||||
|
@ -24,15 +28,15 @@ Before continuing, verify correct records with an authoritative lookup. Replace
|
|||
<pre><code class="cmd bash">curl "https://cloudflare-dns.com/dns-query?name=example.com&type=A" \
|
||||
-H "accept: application/dns-json"</code></pre>
|
||||
|
||||
<aside class="tip">If you're on your home network or some other restricted intranet, you may need to forward ports or adjust firewall settings.</aside>
|
||||
|
||||
Also make sure your server is externally reachable on ports 80 and 443 from a public interface.
|
||||
|
||||
<aside class="tip">If you're on your home or other restricted network, you may need to forward ports or adjust firewall settings.</aside>
|
||||
|
||||
All we have to do is start Caddy with your domain name in the config. There are several ways to do this.
|
||||
|
||||
## Caddyfile
|
||||
|
||||
This is the most common way to get HTTPS; it works for almost any kind of site.
|
||||
This is the most common way to get HTTPS.
|
||||
|
||||
Create a file called `Caddyfile` (no extension) where the first line is your domain name, for example:
|
||||
|
||||
|
@ -46,12 +50,12 @@ Then from the same directory, run:
|
|||
|
||||
<pre><code class="cmd bash">caddy run</code></pre>
|
||||
|
||||
You will see Caddy provision a TLS certificate and serve your site over HTTPS.
|
||||
You will see Caddy provision a TLS certificate and serve your site over HTTPS. This was possible because your site's address in the Caddyfile contained a domain name.
|
||||
|
||||
|
||||
## The `file-server` command
|
||||
|
||||
If all you need is a file server over HTTPS, run this command (replacing your domain name):
|
||||
If all you need is serving static files over HTTPS, run this command (replacing your domain name):
|
||||
|
||||
<pre><code class="cmd bash">caddy file-server --domain example.com</code></pre>
|
||||
|
||||
|
@ -69,7 +73,7 @@ You will see Caddy provision a TLS certificate and serve your site over HTTPS.
|
|||
|
||||
## JSON config
|
||||
|
||||
The general rule of thumb is that any [host matcher](/docs/json/apps/http/servers/routes/match/host/) with a host that looks like a domain name will trigger automatic HTTPS.
|
||||
The general rule of thumb is that any [host matcher](/docs/json/apps/http/servers/routes/match/host/) will trigger automatic HTTPS.
|
||||
|
||||
Thus, a JSON config such as the following will enable production-ready [automatic HTTPS](/docs/automatic-https):
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ Caddy 2's default protocol is [_always_ HTTPS if a hostname or IP is known](/doc
|
|||
|
||||
IP addresses and localhost domains will be issued certificates from a [locally-trusted, embedded CA](/docs/automatic-https#local-https). All other domains will use Let's Encrypt. (This is all configurable.)
|
||||
|
||||
The storage structure of certificates and ACME resources has changed. Caddy 2 will probably obtain new certificates for your sites; but if you have a lot of certificates you can migrate them manually. See issues [#2955](https://github.com/caddyserver/caddy/issues/2955) and [#3124](https://github.com/caddyserver/caddy/issues/3124) for details.
|
||||
The storage structure of certificates and ACME resources has changed. Caddy 2 will probably obtain new certificates for your sites; but if you have a lot of certificates you can migrate them manually if it does not do it for you. See issues [#2955](https://github.com/caddyserver/caddy/issues/2955) and [#3124](https://github.com/caddyserver/caddy/issues/3124) for details.
|
||||
|
||||
|
||||
## Command line
|
||||
|
@ -96,7 +96,7 @@ Environment variables are no longer relevant, except for `HOME` (and, optionally
|
|||
|
||||
The [v2 Caddyfile](/docs/caddyfile/concepts) is very similar to what you're already familiar with. The main thing you'll need to do is change your directives.
|
||||
|
||||
⚠️ **Do not take this advice at face value!** Especially if your config is more advanced, there are many nuances to consider. These tips will get you mostly switched over pretty quickly, but please read the full documentation for each directive so you can understand the implications of the upgrade. And of course, always test your configs thoroughly before putting them into production.
|
||||
⚠️ **Be sure to read into the new directives!** Especially if your config is more advanced, there are many nuances to consider. These tips will get you mostly switched over pretty quickly, but please read the full documentation for each directive so you can understand the implications of the upgrade. And of course, always test your configs thoroughly before putting them into production.
|
||||
|
||||
### Primary changes
|
||||
|
||||
|
@ -105,15 +105,15 @@ The [v2 Caddyfile](/docs/caddyfile/concepts) is very similar to what you're alre
|
|||
|
||||
- In v1, you could only filter (or "match") directives by request path. In v2, [request matching](/docs/caddyfile/matchers) is much more powerful. Any v2 directives which add a middleware to the HTTP handler chain or which manipulate the HTTP request/response in any way take advantage of this new matching functionality. [Read more about v2 request matchers.](/docs/caddyfile/matchers) You'll need to know about them to make sense of the v2 Caddyfile.
|
||||
|
||||
- Although many [placeholders](/docs/conventions#placeholders) are the same, many have changed, and there are now [many new ones](/docs/modules/http), including [shorthands for the Caddyfile](/docs/caddyfile/concepts#placeholders).
|
||||
- Although many [placeholders](/docs/conventions#placeholders) are the same, many have changed, and there are now [many new ones](/docs/modules/http#docs), including [shorthands for the Caddyfile](/docs/caddyfile/concepts#placeholders).
|
||||
|
||||
- Caddy 2 logs are all structured, and the default format is JSON. All log levels can simply go to the same log to be processed (but you can customize this if needed).
|
||||
|
||||
- Where you matched requests by path prefix in Caddy 1, path matching is now exact by default in Caddy 2, so if you want to match a prefix, for example `/foo/`, you'll need `/foo/*` in Caddy 2.
|
||||
- Where you matched requests by path prefix in Caddy 1, path matching is now exact by default in Caddy 2. If you want to match a prefix like `/foo/`, you'll need `/foo/*` in Caddy 2.
|
||||
|
||||
We'll list some of the most common v1 directives here and describe how to convert them for use in the v2 Caddyfile.
|
||||
|
||||
⚠️ **Just because a v1 directive is missing from this page does not mean v2 can't do it!** Some v1 directives aren't needed, don't translate well, or are fulfilled other ways in v2. For some advanced customization, you may need to drop down to the JSON to get what you want. Explore our documentation to find what you need!
|
||||
⚠️ **Just because a v1 directive is missing from this page does not mean v2 can't do it!** Some v1 directives aren't needed, don't translate well, or are fulfilled other ways in v2. For some advanced customization, you may need to drop down to the JSON to get what you want. Explore [our documentation](/docs/caddyfile) to find what you need!
|
||||
|
||||
|
||||
### browse
|
||||
|
@ -143,6 +143,8 @@ Note that the `fastcgi` directive from v1 did a lot under the hood, including tr
|
|||
|
||||
There is no `php` preset needed in v2, since the `php_fastcgi` directive assumes PHP by default. A line such as `php_fastcgi 127.0.0.1:9000 php` will cause the reverse proxy to think that there is a second backend called `php`, leading to connection errors.
|
||||
|
||||
The subdirectives are different in v2 -- you probably will not need any for PHP.
|
||||
|
||||
|
||||
### gzip
|
||||
|
||||
|
@ -158,15 +160,23 @@ Fun fact: Caddy 2 also supports `zstd` (but no browsers do yet).
|
|||
|
||||
[Mostly unchanged](/docs/caddyfile/directives/header), but now way more powerful since it can do substring replacements in v2.
|
||||
|
||||
- **v1:** `header / Strict-Transport-Security "max-age=31536000;"`
|
||||
- **v2:** `header Strict-Transport-Security "max-age=31536000;"`
|
||||
- **v1:** `header / Strict-Transport-Security max-age=31536000;`
|
||||
- **v2:** `header Strict-Transport-Security max-age=31536000;`
|
||||
|
||||
|
||||
### log
|
||||
|
||||
Enables access logging; the [`log`](/docs/caddyfile/directives/log) directive can still be used in v2, but all logs are structured, encoded as JSON, by default.
|
||||
|
||||
Although we recommend everyone use structured logging (it is much more flexible), you can still write Common Log Format to a file, if you must:
|
||||
The recommended way to enable access logging is simply:
|
||||
|
||||
```
|
||||
log
|
||||
```
|
||||
|
||||
which emits structured logs to stderr. (You can also emit to a file or network socket; see docs.)
|
||||
|
||||
Although we recommend everyone use [structured logging](/docs/logging), you can still write Common Log Format (CLF) to a file, if you must:
|
||||
|
||||
- **v1:**
|
||||
```
|
||||
|
@ -181,6 +191,8 @@ log {
|
|||
}
|
||||
```
|
||||
|
||||
But we recommend this only for transitioning while your legacy systems still require CLF.
|
||||
|
||||
|
||||
### proxy
|
||||
|
||||
|
|
|
@ -13,42 +13,33 @@
|
|||
<main>
|
||||
{{include "/includes/docs-nav.html"}}
|
||||
<div class="article-container">
|
||||
|
||||
<div id="module-list-container">
|
||||
<article>
|
||||
<h1>All Modules</h1>
|
||||
<p>
|
||||
This page lists all registered Caddy modules.
|
||||
</p>
|
||||
<p>
|
||||
We recommend using your browser's "Find in page" feature for quick lookups.
|
||||
</p>
|
||||
<table id="module-list">
|
||||
<tr>
|
||||
<th>Module ID</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<!-- Populated by JS-->
|
||||
</table>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div id="module-docs-container">
|
||||
<article>
|
||||
<h1 id="module-name"><!--Populated by JS--></h1>
|
||||
</article>
|
||||
<div class="paper" id="paper1"></div>
|
||||
<div class="paper" id="paper2"></div>
|
||||
<article id="module-list-container" class="paper paper3">
|
||||
<h1>All Modules</h1>
|
||||
<p>
|
||||
This page lists all registered Caddy modules.
|
||||
</p>
|
||||
<p>
|
||||
We recommend using your browser's "Find in page" feature for quick lookups.
|
||||
</p>
|
||||
<table id="module-list">
|
||||
<tr>
|
||||
<th>Module ID</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<!--Populated by JS-->
|
||||
</table>
|
||||
</article>
|
||||
<article id="module-docs-container" class="paper paper3">
|
||||
<h1 id="module-name"><!--Populated by JS--></h1>
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
<article>
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
</div>
|
||||
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
</div>
|
||||
<div class="sidebar"></div>
|
||||
</main>
|
||||
|
||||
{{include "/includes/docs-hovercard.html"}}
|
||||
|
||||
{{include "/includes/footer.html"}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<p id="top-doc">
|
||||
<h2 id="docs">Description</h2>
|
||||
<div id="top-doc">
|
||||
<!--Populated by JS-->
|
||||
</p>
|
||||
<h2 id="field-list-header">Field List</h2>
|
||||
<dl id="field-list">
|
||||
</div>
|
||||
<h2 id="field-list">Field List</h2>
|
||||
<dl id="field-list-contents">
|
||||
<!--Populated by JS-->
|
||||
</dl>
|
|
@ -1,4 +1,5 @@
|
|||
{{include "/includes/head.html"}}
|
||||
<link rel="stylesheet" href="/resources/css/docs.css">
|
||||
<link rel="stylesheet" href="/resources/css/chroma.css">
|
||||
<script src="/resources/js/jquery-3.4.1.min.js"></script>
|
||||
<script src="/resources/js/docs.js"></script>
|
|
@ -1,15 +1,13 @@
|
|||
<div class="wrapper">
|
||||
<footer>
|
||||
<div>
|
||||
<img src="/resources/images/caddy-logo.svg" alt="Caddy" id="footer-logo">
|
||||
An <a href="https://github.com/caddyserver/caddy">open source</a> Go community project
|
||||
<br>
|
||||
in partnership with <a href="https://www.ardanlabs.com/">Ardan Labs</a>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
© 2015-{{now | date "2006"}} Light Code Labs. All rights reserved.
|
||||
<br>
|
||||
Caddy® is a registered trademark of Light Code Labs, LLC.
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<footer>
|
||||
<div>
|
||||
<img src="/resources/images/caddy-logo.svg" alt="Caddy" id="footer-logo">
|
||||
An <a href="https://github.com/caddyserver/caddy">open source</a> Go community project
|
||||
<br>
|
||||
in partnership with <a href="https://www.ardanlabs.com/">Ardan Labs</a>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
© 2015-{{now | date "2006"}} Light Code Labs. All rights reserved.
|
||||
<br>
|
||||
Caddy® is a registered trademark of Light Code Labs, LLC.
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<br>
|
||||
then <a href="/docs/getting-started">learn how to get started</a>
|
||||
<br><br>
|
||||
<a href="/v1/download" class="gray button">Download v1.0 stable</a>
|
||||
<a href="https://github.com/caddyserver/caddy/releases/v1.0.5" class="gray button">Download v1.0</a>
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=caddyserver&repo=caddy&type=star&count=true&size=large" frameborder="0" scrolling="0" width="160px" height="30px" class="github-stars"></iframe>
|
||||
<br>
|
||||
<small>Caddy is licensed with the Apache 2.0 open source license.</small>
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
Solarized Light (High Contrast)
|
||||
Derived from http://ethanschoonover.com/solarized
|
||||
*/
|
||||
.chroma { background-color: #f0f9fb; color: #586e75 }
|
||||
.chroma {
|
||||
background: linear-gradient(0deg, #f8fbfd 0%, #edf5fd 100%);
|
||||
color: #254048;
|
||||
}
|
||||
.chroma .c { color: #93a1a1 } /* Comment */
|
||||
.chroma .err { color: #586e75 } /* Error */
|
||||
.chroma .g { color: #586e75 } /* Generic */
|
||||
|
@ -83,7 +86,10 @@
|
|||
Solarized Dark (High Contrast)
|
||||
Derived from http://ethanschoonover.com/solarized
|
||||
*/
|
||||
.chroma { background-color: #002b36; color: #93a1a1 }
|
||||
.chroma {
|
||||
background: linear-gradient(0deg, #18384d 0%, #122537 100%);
|
||||
color: #93a1a1;
|
||||
}
|
||||
.chroma .c { color: #586e75 } /* Comment */
|
||||
.chroma .err { color: #93a1a1 } /* Error */
|
||||
.chroma .g { color: #93a1a1 } /* Generic */
|
||||
|
|
|
@ -14,16 +14,16 @@ body {
|
|||
|
||||
#v1-banner {
|
||||
display: block;
|
||||
background: #5ea9a2;
|
||||
background: #5c92a4;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 15px 25px;
|
||||
font-size: 18px;
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#v1-banner:hover {
|
||||
background: #4e968f;
|
||||
background: #457a8c;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
|
@ -89,8 +89,12 @@ header nav > a.current {
|
|||
width: 150px;
|
||||
max-width: 100%;
|
||||
margin-right: 20px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#search:focus {
|
||||
background: #fff;
|
||||
}
|
||||
/* End Algolia search */
|
||||
|
||||
header nav .button {
|
||||
|
@ -166,9 +170,7 @@ footer {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 100px;
|
||||
border-top: 1px solid #CCC;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 100px;
|
||||
padding: 0 50px 100px;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
pre > code.json {
|
||||
background-color: #f0f9f8;
|
||||
article {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
article h1 {
|
||||
padding-top: 8%;
|
||||
}
|
||||
|
||||
#renderbox {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
body {
|
||||
font-family: Maven Pro, sans-serif;
|
||||
background: #f1f4f5;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: 1px solid #f0f6f7;
|
||||
padding: 10px 20px;
|
||||
padding: 20px 40px;
|
||||
}
|
||||
|
||||
#logo-container {
|
||||
|
@ -20,8 +20,9 @@ header {
|
|||
|
||||
#logo-docs {
|
||||
font-family: Montserrat, sans-serif;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: #196165;
|
||||
color: #0e495e;
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
@ -37,14 +38,22 @@ header nav .button {
|
|||
}
|
||||
|
||||
.breadcrumbs {
|
||||
color: #196165;
|
||||
border-bottom: 1px solid #f0f6f7;
|
||||
padding: 10px 20px !important;
|
||||
margin-bottom: 0 !important;
|
||||
color: #2861aa;
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
font-weight: bold;
|
||||
line-height: 1.75em;
|
||||
}
|
||||
|
||||
#top-breadcrumb {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#top-breadcrumb:not(:hover) {
|
||||
color: #2861aa;
|
||||
}
|
||||
|
||||
.breadcrumbs a {
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
|
@ -69,33 +78,26 @@ header nav .button {
|
|||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#top-breadcrumb {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#top-breadcrumb:not(:hover) {
|
||||
color: #196165;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
main > .sidebar,
|
||||
article aside {
|
||||
width: 20%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
main > .sidebar {
|
||||
width: 18%;
|
||||
flex-shrink: 0;
|
||||
padding: 20px 0;
|
||||
border: 0px solid #f0f6f7;
|
||||
flex-grow: 1;
|
||||
padding: 20px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
main nav {
|
||||
border-right-width: 1px;
|
||||
main > .sidebar:last-child {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
main > nav.sidebar {
|
||||
position: relative;
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
main nav ul {
|
||||
|
@ -106,19 +108,19 @@ main nav li {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
main nav li a {
|
||||
padding: 8px 22px;
|
||||
}
|
||||
|
||||
main nav li a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
border-radius: 1.5em;
|
||||
padding: 6px 18px 6px 28px;
|
||||
color: #546c75;
|
||||
}
|
||||
|
||||
|
||||
|
||||
main nav li a:hover {
|
||||
background-color: #f8fcff;
|
||||
color: #196165;
|
||||
color: #01324b;
|
||||
}
|
||||
|
||||
main nav li a:before {
|
||||
|
@ -128,13 +130,13 @@ main nav li a:before {
|
|||
line-height: 1rem;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
left: 5px;
|
||||
left: 0;
|
||||
transition: left .15s, opacity .15s;
|
||||
}
|
||||
|
||||
main nav li a:hover:before {
|
||||
opacity: 1;
|
||||
left: 10px;
|
||||
left: .75em;
|
||||
}
|
||||
|
||||
main nav li li a:hover:before {
|
||||
|
@ -142,13 +144,15 @@ main nav li li a:hover:before {
|
|||
}
|
||||
|
||||
main nav li a.current {
|
||||
background-color: #f0f6f7;
|
||||
background-color: #e0e8f0;
|
||||
}
|
||||
|
||||
main nav li.heading {
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
padding: 10px 20px 5px;
|
||||
text-transform: uppercase;
|
||||
font-size: 90%;
|
||||
letter-spacing: 1px;
|
||||
padding: 10px 20px 10px 2em;
|
||||
}
|
||||
|
||||
main nav li.heading:not(:first-child) {
|
||||
|
@ -158,33 +162,90 @@ main nav li.heading:not(:first-child) {
|
|||
main nav li li a {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 2.5em;
|
||||
padding-left: 3em;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.article-container {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
.paper {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 2px 4px 1px rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
article,
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
max-width: 950px;
|
||||
#paper1,
|
||||
#paper2 {
|
||||
background: #f8fafb;
|
||||
max-height: 1500px;
|
||||
}
|
||||
|
||||
#paper1 {
|
||||
top: -20px;
|
||||
left: 20px;
|
||||
transform: rotate(3deg);
|
||||
}
|
||||
|
||||
#paper2 {
|
||||
top: 30px;
|
||||
left: -100%;
|
||||
transform: rotate(-5deg);
|
||||
}
|
||||
|
||||
.paper3 {
|
||||
top: 20px;
|
||||
left: -200%;
|
||||
}
|
||||
|
||||
.article-container {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
margin: 20px;
|
||||
width: 100%;
|
||||
max-width: 1100px;
|
||||
}
|
||||
|
||||
article {
|
||||
padding: 40px;
|
||||
padding-top: 8%;
|
||||
padding-bottom: 8%;
|
||||
font-size: 20px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/*
|
||||
while we want most elements that are rendered
|
||||
server-side from markdown to have a constrained
|
||||
width, a few elements should be allowed to
|
||||
extend to the borders of the page
|
||||
*/
|
||||
article > :not(.fullwidth),
|
||||
article > .fullwidth > * {
|
||||
padding-left: 8%;
|
||||
padding-right: 8%;
|
||||
}
|
||||
article > :not(h1),
|
||||
dd,
|
||||
article p,
|
||||
article pre > code,
|
||||
article pre.chroma,
|
||||
article ol,
|
||||
article ul,
|
||||
article ol {
|
||||
margin-bottom: 1em;
|
||||
article pre,
|
||||
article table {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
article > .fullwidth { margin-bottom: 1.5rem; }
|
||||
article > .fullwidth > * { margin-bottom: 0; }
|
||||
|
||||
article > pre.chroma > code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
article > pre.chroma {
|
||||
padding-top: 2em;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
article ul,
|
||||
|
@ -194,22 +255,45 @@ article ol,
|
|||
margin-left: 2.5em;
|
||||
}
|
||||
|
||||
article ul ul,
|
||||
article ol ol,
|
||||
article ol ul,
|
||||
article ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
article p,
|
||||
article li {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
/* to ensure that the anchor-link icons stay inside the heading */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 80px;
|
||||
color: #196165;
|
||||
font-size: 72px;
|
||||
color: #0e3e5b;
|
||||
letter-spacing: -2px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 46px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 4px solid #a6d0da;
|
||||
margin: 100px 0 40px;
|
||||
border-bottom: 4px solid #72abe8;
|
||||
margin: 100px 0 40px !important;
|
||||
}
|
||||
|
||||
h3 {
|
||||
|
@ -227,35 +311,37 @@ h5 {
|
|||
margin: 2em 0 1em;
|
||||
}
|
||||
|
||||
/* Styles from https://github.com/bryanbraun/anchorjs */
|
||||
@font-face {
|
||||
font-family: "anchor-icons";
|
||||
src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype");
|
||||
}
|
||||
.anchor-link {
|
||||
opacity: 0;
|
||||
font: 1em / 1 anchor-icons;
|
||||
text-decoration: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
padding-left: 0.375em;
|
||||
font-size: .6em;
|
||||
border-radius: 10px;
|
||||
padding: .3em .5em;
|
||||
margin-left: .25em;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
*:hover > .anchor-link,
|
||||
.anchor-link:focus {
|
||||
opacity: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
code,
|
||||
pre.chroma {
|
||||
.anchor-link:hover {
|
||||
background-color: rgba(0, 0, 0, .075);
|
||||
}
|
||||
|
||||
pre,
|
||||
code {
|
||||
font-family: 'PT Mono', 'Source Code Pro', monospace;
|
||||
padding: 3px 6px;
|
||||
border-radius: 5px;
|
||||
font-size: 90%;
|
||||
line-height: 1.4em;
|
||||
font-size: 95%;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f0f9fb;
|
||||
background-color: #e9f1fb;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
code.cmd {
|
||||
|
@ -271,15 +357,13 @@ pre.chroma,
|
|||
}
|
||||
|
||||
pre > code,
|
||||
pre.chroma {
|
||||
article > pre {
|
||||
padding: 1em;
|
||||
border-radius: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
pre > code.cmd {
|
||||
border-radius: 5px;
|
||||
tab-size: 2;
|
||||
}
|
||||
|
||||
code.cmd.bash,
|
||||
|
@ -308,7 +392,7 @@ dd {
|
|||
.field-name {
|
||||
display: block;
|
||||
font-family: 'Source Code Pro', monospace;
|
||||
margin: 0;
|
||||
margin-top: 2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
@ -316,9 +400,9 @@ dd {
|
|||
.inline-link {
|
||||
text-decoration: none;
|
||||
position: absolute;
|
||||
margin-left: -1.4em;
|
||||
margin-top: -.1em;
|
||||
padding-right: .2em;
|
||||
margin-left: -1.5em;
|
||||
/* margin-top: -.1em; */
|
||||
padding-right: .3em;
|
||||
padding-left: .2em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
@ -329,8 +413,8 @@ dd {
|
|||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 5px solid #186165;
|
||||
margin: 2em 0;
|
||||
border-top: 8px solid #34669b;
|
||||
margin: 4em 0;
|
||||
}
|
||||
|
||||
article img {
|
||||
|
@ -341,10 +425,6 @@ iframe {
|
|||
margin: 1em 0 2em;
|
||||
}
|
||||
|
||||
main > .sidebar:not(:last-child) {
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -357,7 +437,7 @@ main > .sidebar:not(:last-child) {
|
|||
.json .num { color: #038a3f; }
|
||||
.json .bool { color: #9b5e14; }
|
||||
.json .key a:not([href]) { color: #222; }
|
||||
.json a {
|
||||
article .json a {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -485,74 +565,71 @@ main > .sidebar:not(:last-child) {
|
|||
color: #777;
|
||||
}
|
||||
|
||||
.beta-warning {
|
||||
font-size: 14px;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid orange;
|
||||
background: #fff5e2;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
article aside {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
color: #146673;
|
||||
line-height: 1.4em;
|
||||
padding: 10px 3.5% 10px 20px;
|
||||
border: 0px solid #dff9ff;
|
||||
border-top-width: 1px;
|
||||
border-left-width: 1px;
|
||||
background: -webkit-radial-gradient(top left, #d6f0f3, transparent 65%);
|
||||
background: -moz-radial-gradient(top left, #d6f0f3, transparent 65%);
|
||||
background: radial-gradient(top left, #d6f0f3, transparent 65%);
|
||||
margin: 2em auto 3em !important;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
article aside.complete::before,
|
||||
article aside.tip::before {
|
||||
text-transform: uppercase;
|
||||
display: block;
|
||||
line-height: 1em;
|
||||
font-weight: 900;
|
||||
article aside.tip,
|
||||
article aside.advice {
|
||||
padding-left: calc(8% + 50px) !important;
|
||||
}
|
||||
|
||||
article aside.tip::before,
|
||||
article aside.advice::before {
|
||||
font-size: 45px;
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
left: 8%;
|
||||
}
|
||||
|
||||
article aside.tip {
|
||||
color: #706b95;
|
||||
}
|
||||
article aside.advice {
|
||||
color: #826848;
|
||||
}
|
||||
|
||||
article aside.tip:nth-child(even)::before {
|
||||
content: '💁♀️';
|
||||
}
|
||||
article aside.tip:nth-child(odd)::before {
|
||||
content: '💁♂️';
|
||||
}
|
||||
|
||||
article aside.advice::before {
|
||||
content: '🤦';
|
||||
}
|
||||
|
||||
article aside.complete {
|
||||
color: #6b6b6b;
|
||||
border: 2px dotted #88db88;
|
||||
text-align: center;
|
||||
max-width: 500px;
|
||||
padding: 15px 25px !important;
|
||||
}
|
||||
|
||||
article aside.complete::before {
|
||||
content: 'complete';
|
||||
content: '✅ complete';
|
||||
color: #39c849;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
letter-spacing: 2px;
|
||||
color: #3ea78a;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
article aside.tip::before {
|
||||
content: 'tip';
|
||||
color: #d0efef;
|
||||
position: absolute;
|
||||
top: -30px;
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
article aside.warning {
|
||||
border-top-color: #ffd6a4;
|
||||
color: #bd6800;
|
||||
background: -webkit-radial-gradient(top left, #ffd6a4, transparent 65%);
|
||||
background: -moz-radial-gradient(top left, #ffd6a4, transparent 65%);
|
||||
background: radial-gradient(top left, #ffd6a4, transparent 65%);
|
||||
}
|
||||
|
||||
article aside.warning::before {
|
||||
content: 'warning';
|
||||
color: #ffd6a4;
|
||||
position: absolute;
|
||||
top: -30px;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
margin-right: 2em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
table {
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
font-size: 16px;
|
||||
margin: 25px 0;
|
||||
}
|
||||
|
||||
article > table {
|
||||
margin: 25px auto;
|
||||
}
|
||||
|
||||
th, td {
|
||||
|
@ -619,10 +696,6 @@ td code {
|
|||
|
||||
|
||||
@media (max-width: 1400px) {
|
||||
article aside {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
table {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
@ -642,53 +715,66 @@ td code {
|
|||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
main > .sidebar:last-child,
|
||||
article aside {
|
||||
display: none;
|
||||
@media (max-width: 1100px) {
|
||||
header {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
main > .sidebar {
|
||||
width: 30%;
|
||||
padding: 10px 0;
|
||||
min-width: 200px;
|
||||
padding: 20px 10px 0 0;
|
||||
}
|
||||
|
||||
main > .sidebar:last-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#paper1,
|
||||
#paper2 {
|
||||
display: none;
|
||||
}
|
||||
.paper3 {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
article {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1000px) and (min-width: 600px) {
|
||||
main nav li a {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
main nav li li a {
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
main nav li a:before {
|
||||
font-size: 18px;
|
||||
left: -5px;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
main nav li a:hover:before {
|
||||
left: 2px;
|
||||
|
||||
article > :not(.fullwidth),
|
||||
article > .fullwidth > * {
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
main nav li li a:hover:before {
|
||||
left: .5em;
|
||||
article > :not(h1) {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
article > pre.chroma {
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 45px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 600px) {
|
||||
@media (max-width: 700px) {
|
||||
#logo-docs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main {
|
||||
flex-direction: column-reverse;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
main > .sidebar {
|
||||
|
@ -696,6 +782,20 @@ td code {
|
|||
border-width: 0;
|
||||
border-top-width: 2px;
|
||||
}
|
||||
|
||||
.article-container {
|
||||
max-width: 100%; /* TODO: why is this necessary?? without it, article overflows super wide on narrow screen */
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.paper {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.anchor-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -706,10 +806,20 @@ td code {
|
|||
color: #bdd6f7;
|
||||
}
|
||||
|
||||
header,
|
||||
main > .sidebar,
|
||||
footer {
|
||||
border-color: #061b35;
|
||||
#search {
|
||||
background: rgb(28, 52, 79);
|
||||
color: #bdd6f7;
|
||||
}
|
||||
#search:focus {
|
||||
background: rgb(46, 70, 96);
|
||||
}
|
||||
|
||||
#paper1,
|
||||
#paper2 {
|
||||
background-color: #030a11;
|
||||
}
|
||||
.paper3 {
|
||||
background-color: #051628;
|
||||
}
|
||||
|
||||
#logo {
|
||||
|
@ -725,8 +835,11 @@ td code {
|
|||
color: #5aa3dc;
|
||||
}
|
||||
|
||||
main nav li a {
|
||||
color: #668d9b;
|
||||
}
|
||||
|
||||
main nav ul li a:hover {
|
||||
background-color: #13243a;
|
||||
color: #5aa3dc;
|
||||
}
|
||||
|
||||
|
@ -734,8 +847,7 @@ td code {
|
|||
background-color: #061b35;
|
||||
}
|
||||
|
||||
.breadcrumbs,
|
||||
main nav {
|
||||
.breadcrumbs {
|
||||
border-color: #061b35;
|
||||
}
|
||||
|
||||
|
@ -777,35 +889,9 @@ td code {
|
|||
#hovercard-inline-link {
|
||||
border-color: #0a2b53;
|
||||
}
|
||||
|
||||
|
||||
.beta-warning {
|
||||
background-color: #462e00;
|
||||
color: #ffa500;
|
||||
}
|
||||
|
||||
article aside {
|
||||
background: -webkit-radial-gradient(top left, #00515a, transparent 65%);
|
||||
background: -moz-radial-gradient(top left, #00515a, transparent 65%);
|
||||
background: radial-gradient(top left, #00515a, transparent 65%);
|
||||
color: #37c3a9;
|
||||
border-color: #08575a;
|
||||
}
|
||||
|
||||
article aside.warning {
|
||||
border-top-color: #462e00;
|
||||
color: #e1973b;
|
||||
background: -webkit-radial-gradient(top left, #462e00, transparent 65%);
|
||||
background: -moz-radial-gradient(top left, #462e00, transparent 65%);
|
||||
background: radial-gradient(top left, #462e00, transparent 65%);
|
||||
border-left-color: #462e00;
|
||||
}
|
||||
article aside.warning::before {
|
||||
color: #e1973b;
|
||||
}
|
||||
|
||||
article aside.tip:before {
|
||||
color: #185f5b;
|
||||
article aside.tip {
|
||||
color: #8c81e4;
|
||||
}
|
||||
|
||||
th {
|
||||
|
|
|
@ -34,7 +34,7 @@ $(function() {
|
|||
// don't allow hoverbox to close anymore, we're re-opening it
|
||||
clearTimeout(hoverTimeout);
|
||||
|
||||
var pos = $(this).position();
|
||||
var pos = $(this).offset();
|
||||
|
||||
// there is a gap between the hoverbox and the link that originated it;
|
||||
// there may be a different link in this gap; if the hover box is visible,
|
||||
|
@ -43,7 +43,7 @@ $(function() {
|
|||
// visit the hoverbox while it is over a list of links that are tightly
|
||||
// stacked vertically; if user wants to visit hoverbox for link in this
|
||||
// gap, they can just move the cursor slow enough to fire the timeout
|
||||
if ($hovercard.is(':visible') && $hovercard.position().top - 10 < pos.top) {
|
||||
if ($hovercard.is(':visible') && $hovercard.offset().top - 10 < pos.top) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -159,8 +159,16 @@ function beginRendering(json) {
|
|||
renderData(pageData.structure, 0, "", $('<div class="group"/>'));
|
||||
console.log("DOCS:", pageDocs);
|
||||
|
||||
if ($('#field-list').html().trim()) {
|
||||
$('#field-list-header').show();
|
||||
if ($('#field-list-contents').html().trim()) {
|
||||
$('#field-list').show();
|
||||
}
|
||||
|
||||
// if the browser tried to navigate directly to an element
|
||||
// on the page when it loaded, it would have failed since
|
||||
// we hadn't rendered it yet; but now we can scroll to it
|
||||
// directly since rendering has finished
|
||||
if (window.location.hash) {
|
||||
window.location.hash = window.location.hash;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +299,7 @@ function appendToFieldDocs(cleanFieldPath, fieldDoc) {
|
|||
if (canTraverse()) {
|
||||
dt = '<a href="./'+cleanFieldPath+'/">'+dt+'</a>';
|
||||
}
|
||||
$('#field-list').append('<dt class="field-name" id="'+cleanFieldPath+'"><a href="#'+cleanFieldPath+'" class="inline-link">🔗</a>'+dt+'</dt> <dd>'+fieldDoc+'</dd>');
|
||||
$('#field-list-contents').append('<dt class="field-name" id="'+cleanFieldPath+'"><a href="#'+cleanFieldPath+'" class="inline-link">🔗</a>'+dt+'</dt> <dd>'+fieldDoc+'</dd>');
|
||||
}
|
||||
|
||||
function indent(nesting, $group) {
|
||||
|
|
|
@ -18,7 +18,16 @@ $(function() {
|
|||
$currentPageLink.addClass('current');
|
||||
|
||||
// add anchor links, inspired by https://github.com/bryanbraun/anchorjs
|
||||
$('article h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]').each(function() {
|
||||
$(this).append($('<a href="#'+this.id+'" class="anchor-link" aria-label="Anchor"></a>'));
|
||||
$('article > h1[id], article > h2[id], article > h3[id], article > h4[id], article > h5[id], article > h6[id]').each(function() {
|
||||
var $anchor = $('<a href="#'+this.id+'" class="anchor-link" title="Direct link">🔗</a>');
|
||||
$(this).append($anchor);
|
||||
});
|
||||
|
||||
// the server-side markdown renderer annoyingly renders
|
||||
// colored code blocks differently from plain ones, in that
|
||||
// colorized ones do not have the additional <code> inside
|
||||
// the <pre>; this line finds those and adds a .chroma class
|
||||
// to the outer pre element, and our CSS file has a style to
|
||||
// ensure the inner code block does not produce extra padding
|
||||
$('article > pre:not(.chroma) > code:not(.cmd)').parent().addClass('chroma');
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue