mirror of
https://github.com/caddyserver/website.git
synced 2025-04-20 12:15:08 -04:00
docs: Start building quick-assist feature
This commit is contained in:
parent
23e904381c
commit
4c837b4f06
10 changed files with 709 additions and 292 deletions
|
@ -4,11 +4,13 @@
|
|||
<title>Caddy Documentation</title>
|
||||
{{include "/includes/head.html"}}
|
||||
<link rel="stylesheet" href="/resources/css/docs.css">
|
||||
<link rel="stylesheet" href="/resources/css/docs-home.css">
|
||||
<!-- <meta property="og:title" content="Caddy 2 - The Ultimate Server with Automatic HTTPS">
|
||||
<meta name="twitter:title" value="Caddy 2 - The Ultimate Server with Automatic HTTPS"> -->
|
||||
|
||||
<script src="/resources/js/vendor/marked.min.js"></script>
|
||||
<script src="/resources/js/docs.js"></script>
|
||||
<script src="/resources/js/docs-home.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
{{include "/includes/header.html" ""}}
|
||||
|
@ -92,255 +94,91 @@
|
|||
</ul>
|
||||
</nav>
|
||||
|
||||
<article><h1 id="api">Administration API</h1>
|
||||
<p>Caddy is configured through an administration endpoint which can be accessed via HTTP using a <a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> API. You can <a href="/docs/json/admin/">configure this endpoint</a> in your Caddy config.</p>
|
||||
<p><strong>Default address: <code>localhost:2019</code></strong></p>
|
||||
<p>The default address can be changed by setting the <code>CADDY_ADMIN</code> environment variable. Some installation methods may set this to something different. The address in the Caddy config always takes precedence over the default.</p>
|
||||
<aside class="tip">
|
||||
If you are running untrusted code on your server (yikes 😬), make sure you protect your admin endpoint by isolating processes, patching vulnerable programs, and configuring the endpoint to bind to a permissioned unix socket instead.
|
||||
</aside>
|
||||
<p>The latest configuration will be saved to disk after any changes (unless <a href="/docs/json/admin/config/">disabled</a>). You can resume the last working config after a restart with <a href="/docs/command-line#caddy-run"><code>caddy run --resume</code></a>, which guarantees config durability in the event of a power cycle or similar.</p>
|
||||
<p>To get started with the API, try our <a href="/docs/api-tutorial">API tutorial</a> or, if you only have a minute, our <a href="/docs/quick-starts/api">API quick-start guide</a>.</p>
|
||||
<hr>
|
||||
<ul>
|
||||
<li>
|
||||
<p><strong><a href="#post-load">POST /load</a></strong>
|
||||
Sets or replaces the active configuration</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#post-stop">POST /stop</a></strong>
|
||||
Stops the active configuration and exits the process</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#get-configpath">GET /config/[path]</a></strong>
|
||||
Exports the config at the named path</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#post-configpath">POST /config/[path]</a></strong>
|
||||
Sets or replaces object; appends to array</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#put-configpath">PUT /config/[path]</a></strong>
|
||||
Creates new object; inserts into array</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#patch-configpath">PATCH /config/[path]</a></strong>
|
||||
Replaces an existing object or array element</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#delete-configpath">DELETE /config/[path]</a></strong>
|
||||
Deletes the value at the named path</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#using-id-in-json">Using <code>@id</code> in JSON</a></strong>
|
||||
Easily traverse into the config structure</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#concurrent-config-changes">Concurrent config changes</a></strong>
|
||||
Avoid collisions when making unsynchronized changes to config</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#post-adapt">POST /adapt</a></strong>
|
||||
Adapts a configuration to JSON without running it</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#get-pkicaltidgt">GET /pki/ca/<id></a></strong>
|
||||
Returns information about a particular <a href="/docs/json/apps/pki/">PKI app</a> CA</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#get-pkicaltidgtcertificates">GET /pki/ca/<id>/certificates</a></strong>
|
||||
Returns the certificate chain of a particular <a href="/docs/json/apps/pki/">PKI app</a> CA</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong><a href="#get-reverse-proxyupstreams">GET /reverse_proxy/upstreams</a></strong>
|
||||
Returns the current status of the configured proxy upstreams</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="post-load">POST /load</h2>
|
||||
<p>Sets Caddy's configuration, overriding any previous configuration. It blocks until the reload completes or fails. Configuration changes are lightweight, efficient, and incur zero downtime. If the new config fails for any reason, the old config is rolled back into place without downtime.</p>
|
||||
<p>This endpoint supports different config formats using config adapters. The request's Content-Type header indicates the config format used in the request body. Usually, this should be <code>application/json</code> which represents Caddy's native config format. For another config format, specify the appropriate Content-Type so that the value after the forward slash / is the name of the config adapter to use. For example, when submitting a Caddyfile, use a value like <code>text/caddyfile</code>; or for JSON 5, use a value such as <code>application/json5</code>; etc.</p>
|
||||
<p>If the new config is the same as the current one, no reload will occur. To force a reload, set <code>Cache-Control: must-revalidate</code> in the request headers.</p>
|
||||
<h3 id="examples">Examples</h3>
|
||||
<p>Set a new active configuration:</p>
|
||||
<pre><code class="cmd bash">curl "http://localhost:2019/load" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @caddy.json</code></pre>
|
||||
<p>Note: curl's <code>-d</code> flag removes newlines, so if your config format is sensitive to line breaks (e.g. the Caddyfile), use <code>--data-binary</code> instead:</p>
|
||||
<pre><code class="cmd bash">curl "http://localhost:2019/load" \
|
||||
-H "Content-Type: text/caddyfile" \
|
||||
--data-binary @Caddyfile</code></pre>
|
||||
<h2 id="post-stop">POST /stop</h2>
|
||||
<p>Gracefully shuts down the server and exits the process. To only stop the running configuration without exiting the process, use <a href="#delete-configpath">DELETE /config/</a>.</p>
|
||||
<h3 id="example">Example</h3>
|
||||
<p>Stop the process:</p>
|
||||
<pre><code class="cmd bash">curl -X POST "http://localhost:2019/stop"</code></pre>
|
||||
<h2 id="get-configpath">GET /config/[path]</h2>
|
||||
<p>Exports Caddy's current configuration at the named path. Returns a JSON body.</p>
|
||||
<h3 id="examples-1">Examples</h3>
|
||||
<p>Export entire config and pretty-print it:</p>
|
||||
<pre><code class="cmd"><span class="bash">curl "http://localhost:2019/config/" | jq</span>
|
||||
{
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"myserver": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"example.com"
|
||||
]
|
||||
}
|
||||
],
|
||||
"handle": [
|
||||
{
|
||||
"handler": "file_server"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
||||
<p>Export just the listener addresses:</p>
|
||||
<pre><code class="cmd"><span class="bash">curl "http://localhost:2019/config/apps/http/servers/myserver/listen"</span>
|
||||
[":443"]</code></pre>
|
||||
<h2 id="post-configpath">POST /config/[path]</h2>
|
||||
<p>Changes Caddy's configuration at the named path to the JSON body of the request. If the destination value is an array, POST appends; if an object, it creates or replaces.</p>
|
||||
<p>As a special case, many items can be added to an array if:</p>
|
||||
<ol>
|
||||
<li>the path ends in <code>/...</code></li>
|
||||
<li>the element of the path before <code>/...</code> refers to an array</li>
|
||||
<li>the payload is an array</li>
|
||||
</ol>
|
||||
<p>In this case, the elements in the payload's array will be expanded, and each one will be appended to the destination array. In Go terms, this would have the same effect as:</p>
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="nx">baseSlice</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">baseSlice</span><span class="p">,</span> <span class="nx">newElems</span><span class="o">...</span><span class="p">)</span>
|
||||
</span></span></code></pre><h3 id="examples-2">Examples</h3>
|
||||
<p>Add a listener address:</p>
|
||||
<pre><code class="cmd bash">curl \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '":8080"' \
|
||||
"http://localhost:2019/config/apps/http/servers/myserver/listen"</code></pre>
|
||||
<p>Add multiple listener addresses:</p>
|
||||
<pre><code class="cmd bash">curl \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[":8080", ":5133"]' \
|
||||
"http://localhost:2019/config/apps/http/servers/myserver/listen/..."</code></pre>
|
||||
<h2 id="put-configpath">PUT /config/[path]</h2>
|
||||
<p>Changes Caddy's configuration at the named path to the JSON body of the request. If the destination value is a position (index) in an array, PUT inserts; if an object, it strictly creates a new value.</p>
|
||||
<h3 id="example-1">Example</h3>
|
||||
<p>Add a listener address in the first slot:</p>
|
||||
<pre><code class="cmd bash">curl -X PUT \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '":8080"' \
|
||||
"http://localhost:2019/config/apps/http/servers/myserver/listen/0"</code></pre>
|
||||
<h2 id="patch-configpath">PATCH /config/[path]</h2>
|
||||
<p>Changes Caddy's configuration at the named path to the JSON body of the request. PATCH strictly replaces an existing value or array element.</p>
|
||||
<h3 id="example-2">Example</h3>
|
||||
<p>Replace the listener addresses:</p>
|
||||
<pre><code class="cmd bash">curl -X PATCH \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[":8081", ":8082"]' \
|
||||
"http://localhost:2019/config/apps/http/servers/myserver/listen"</code></pre>
|
||||
<h2 id="delete-configpath">DELETE /config/[path]</h2>
|
||||
<p>Removes Caddy's configuration at the named path. DELETE deletes the target value.</p>
|
||||
<h3 id="examples-3">Examples</h3>
|
||||
<p>To unload the entire current configuration but leave the process running:</p>
|
||||
<pre><code class="cmd bash">curl -X DELETE "http://localhost:2019/config/"</code></pre>
|
||||
<p>To stop only one of your HTTP servers:</p>
|
||||
<pre><code class="cmd bash">curl -X DELETE "http://localhost:2019/config/apps/http/servers/myserver"</code></pre>
|
||||
<h2 id="using-id-in-json">Using <code>@id</code> in JSON</h2>
|
||||
<p>You can embed IDs in your JSON document for easier direct access to those parts of the JSON.</p>
|
||||
<p>Simply add a field called <code>"@id"</code> to an object and give it a unique name. For example, if you had a reverse proxy handler that you wanted to access frequently:</p>
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="p">{</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nt">"@id"</span><span class="p">:</span> <span class="s2">"my_proxy"</span><span class="p">,</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nt">"handler"</span><span class="p">:</span> <span class="s2">"reverse_proxy"</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
||||
</span></span></code></pre><p>To use it, simply make a request to the <code>/id/</code> API endpoint in the same way you would to the corresponding <code>/config/</code> endpoint, but without the whole path. The ID takes the request directly into that scope of the config for you.</p>
|
||||
<p>For example, to access the upstreams of the reverse proxy without an ID, the path would be something like</p>
|
||||
<pre><code>/config/apps/http/servers/myserver/routes/1/handle/0/upstreams
|
||||
</code></pre>
|
||||
<p>but with an ID, the path becomes</p>
|
||||
<pre><code>/id/my_proxy/upstreams
|
||||
</code></pre>
|
||||
<p>which is much easier to remember and write by hand.</p>
|
||||
<h2 id="concurrent-config-changes">Concurrent config changes</h2>
|
||||
<aside class="tip">
|
||||
<p>This section is for all <code>/config/</code> endpoints. It is experimental and subject to change.</p>
|
||||
</aside>
|
||||
<p>Caddy's config API provides <a href="https://en.wikipedia.org/wiki/ACID">ACID guarantees</a> for individual requests, but changes that involve more than a single request are subject to collisions or data loss if not properly synchronized.</p>
|
||||
<p>For example, two clients may <code>GET /config/foo</code> at the same time, make an edit within that scope (config path), then call <code>POST|PUT|PATCH|DELETE /config/foo/...</code> at the same time to apply their changes, resulting in a collision: either one will overwrite the other, or the second might leave the config in an unintended state since it was applied to a different version of the config than it was prepared against. This is because the changes are not aware of each other.</p>
|
||||
<p>Caddy's API does not support transactions spanning multiple requests, and HTTP is a stateless protocol. However, you can use the <code>Etag</code> trailer and <code>If-Match</code> header to detect and prevent collisions for any and all changes as a kind of optimistic concurrency control. This is useful if there is any chance that you are using Caddy's <code>/config/...</code> endpoints concurrently without synchronization. All responses to <code>GET /config/...</code> requests have an HTTP trailer called <code>Etag</code> that contains the path and a hash of the contents in that scope (e.g. <code>Etag: "/config/apps/http/servers 65760b8e"</code>). Simply set the <code>If-Match</code> header on a mutative request to that of an Etag trailer from a previous <code>GET</code> request.</p>
|
||||
<p>The basic algorithm for this is as follows:</p>
|
||||
<ol>
|
||||
<li>Perform a <code>GET</code> request to any scope <code>S</code> within the config. Hold onto the <code>Etag</code> trailer of the response.</li>
|
||||
<li>Make your desired change on the returned config.</li>
|
||||
<li>Perform a <code>POST|PUT|PATCH|DELETE</code> request within scope <code>S</code>, setting the <code>If-Match</code> header to the recent <code>Etag</code> value.</li>
|
||||
<li>If the response is HTTP 412 (Precondition Failed), repeat from step 1, or give up after too many attempts.</li>
|
||||
</ol>
|
||||
<p>This algorithm safely allows multiple, overlapping changes to Caddy's configuration without explicit synchronization. It is designed so that simultaneous changes to different parts of the config don't require a retry: only changes that overlap the same scope of the config can possibly cause a collision and thus require a retry.</p>
|
||||
<h2 id="post-adapt">POST /adapt</h2>
|
||||
<p>Adapts a configuration to Caddy JSON without loading or running it. If successful, the resulting JSON document is returned in the response body.</p>
|
||||
<p>The Content-Type header is used to specify the configuration format in the same way that <a href="#post-load">/load</a> works. For example, to adapt a Caddyfile, set <code>Content-Type: text/caddyfile</code>.</p>
|
||||
<p>This endpoint will adapt any configuration format as long as the associated <a href="/docs/config-adapters">config adapter</a> is plugged in to your Caddy build.</p>
|
||||
<h3 id="examples-4">Examples</h3>
|
||||
<p>Adapt a Caddyfile to JSON:</p>
|
||||
<pre><code class="cmd bash">curl "http://localhost:2019/adapt" \
|
||||
-H "Content-Type: text/caddyfile" \
|
||||
--data-binary @Caddyfile</code></pre>
|
||||
<h2 id="get-pkicaltidgt">GET /pki/ca/<id></h2>
|
||||
<p>Returns information about a particular <a href="/docs/json/apps/pki/">PKI app</a> CA by its ID. If the requested CA ID is the default (<code>local</code>), then the CA will be provisioned if it has not already been. Other CA IDs will return an error if they have not been previously provisioned.</p>
|
||||
<pre><code class="cmd"><span class="bash">curl "http://localhost:2019/pki/ca/local" | jq</span>
|
||||
{
|
||||
"id": "local",
|
||||
"name": "Caddy Local Authority",
|
||||
"root_common_name": "Caddy Local Authority - 2022 ECC Root",
|
||||
"intermediate_common_name": "Caddy Local Authority - ECC Intermediate",
|
||||
"root_certificate": "-----BEGIN CERTIFICATE-----\nMIIB ... gRw==\n-----END CERTIFICATE-----\n",
|
||||
"intermediate_certificate": "-----BEGIN CERTIFICATE-----\nMIIB ... FzQ==\n-----END CERTIFICATE-----\n"
|
||||
}</code></pre>
|
||||
<h2 id="get-pkicaltidgtcertificates">GET /pki/ca/<id>/certificates</h2>
|
||||
<p>Returns the certificate chain of a particular <a href="/docs/json/apps/pki/">PKI app</a> CA by its ID. If the requested CA ID is the default (<code>local</code>), then the CA will be provisioned if it has not already been. Other CA IDs will return an error if they have not been previously provisioned.</p>
|
||||
<p>This endpoint is used internally by the <a href="/docs/command-line#caddy-trust"><code>caddy trust</code></a> command to allow installing the CA's root certificate to your system's trust store.</p>
|
||||
<pre><code class="cmd"><span class="bash">curl "http://localhost:2019/pki/ca/local/certificates"</span>
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIByDCCAW2gAwIBAgIQViS12trTXBS/nyxy7Zg9JDAKBggqhkjOPQQDAjAwMS4w
|
||||
...
|
||||
By75JkP6C14OfU733oElfDUMa5ctbMY53rWFzQ==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBpDCCAUmgAwIBAgIQTS5a+3LUKNxC6qN3ZDR8bDAKBggqhkjOPQQDAjAwMS4w
|
||||
...
|
||||
9M9t0FwCIQCAlUr4ZlFzHE/3K6dARYKusR1ck4A3MtucSSyar6lgRw==
|
||||
-----END CERTIFICATE-----</code></pre>
|
||||
<h2 id="get-reverse-proxyupstreams">GET /reverse_proxy/upstreams</h2>
|
||||
<p>Returns the current status of the configured reverse proxy upstreams (backends) as a JSON document.</p>
|
||||
<pre><code class="cmd"><span class="bash">curl "http://localhost:2019/reverse_proxy/upstreams" | jq</span>
|
||||
[
|
||||
{"address": "10.0.1.1:80", "num_requests": 4, "fails": 2},
|
||||
{"address": "10.0.1.2:80", "num_requests": 5, "fails": 4},
|
||||
{"address": "10.0.1.3:80", "num_requests": 3, "fails": 3}
|
||||
]</code></pre>
|
||||
<p>Each entry in the JSON array is a configured <a href="/docs/json/apps/http/servers/routes/handle/reverse_proxy/upstreams/">upstream</a> stored in the global upstream pool.</p>
|
||||
<ul>
|
||||
<li><strong>address</strong> is the dial address of the upstream. For SRV upstreams, this is the <code>lookup_srv</code> DNS name.</li>
|
||||
<li><strong>num_requests</strong> is the amount of active requests currently being handled by the upstream.</li>
|
||||
<li><strong>fails</strong> the current number of failed requests remembered, as configured by passive health checks.</li>
|
||||
</ul>
|
||||
<p>If your goal is to determine a backend's availability, you will need to cross-check relevant properties of the upstream against the handler configuration you are utilizing. For example, if you've enabled <a href="/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/">passive health checks</a> for your proxies, then you need to also take into consideration the <code>fails</code> and <code>num_requests</code> values to determine if an upstream is considered available: check that the <code>fails</code> amount is less than your configured maximum amount of failures for your proxy (i.e. <a href="/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/max_fails/"><code>max_fails</code></a>), and that <code>num_requests</code> is less than or equal to your configured amount of maximum requests per upstream (i.e. <a href="/docs/json/apps/http/servers/routes/handle/reverse_proxy/health_checks/passive/unhealthy_request_count/"><code>unhealthy_request_count</code></a> for the whole proxy, or <a href="/docs/json/apps/http/servers/routes/handle/reverse_proxy/upstreams/max_requests/"><code>max_requests</code></a> for individual upstreams).</p>
|
||||
</article>
|
||||
<article>
|
||||
<h1>Documentation</h1>
|
||||
|
||||
<div class="fullspan">
|
||||
<div class="box box-filled box-capped quick-assist">
|
||||
<div class="box-cap quick-assist-history">
|
||||
<a title="Click quick for slick trick (not AI)">Quick Assist</a>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="quick-assist-question"></h3>
|
||||
<div class="quick-assist-content"></div>
|
||||
<div class="quick-assist-options"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>Getting Started</h3>
|
||||
<p>
|
||||
New here? Welcome! As usual, before running any server software, please make sure you:
|
||||
</p>
|
||||
<ul>
|
||||
<li>know how to use your terminal / command line</li>
|
||||
<li>are familiar with installing and using non-graphical software</li>
|
||||
<li>can edit text files to configure programs</li>
|
||||
<li>understand how your operating system's network stack and permissions model work</li>
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Caddyfile Directives</h3>
|
||||
<p>
|
||||
Quick access to all standard Caddyfile directives:
|
||||
</p>
|
||||
<ul>
|
||||
<li><code><a href="/docs/caddyfile/directives/abort">abort</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/acme_server">acme_server</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/basicauth">basicauth</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/bind">bind</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/encode">encode</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/error">error</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/file_server">file_server</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/forward_auth">forward_auth</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/handle">handle</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/handle_errors">handle_errors</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/handle_path">handle_path</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/header">header</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/import">import</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/log">log</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/map">map</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/method">method</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/metrics">metrics</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/php_fastcgi">php_fastcgi</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/push">push</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/redir">redir</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/request_body">request_body</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/request_header">request_header</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/respond">respond</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/reverse_proxy">reverse_proxy</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/rewrite">rewrite</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/root">root</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/route">route</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/skip_log">skip_log</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/templates">templates</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/tls">tls</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/tracing">tracing</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/try_files">try_files</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/uri">uri</a></code></li>
|
||||
<li><code><a href="/docs/caddyfile/directives/vars">vars</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Examples</h3>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<nav id="pagenav">
|
||||
<div class="heading">On this page</div>
|
||||
</nav>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -46,7 +46,7 @@
|
|||
</svg>
|
||||
Install
|
||||
</b>
|
||||
Learn how to build or download then install Caddy
|
||||
Various ways to install Caddy on your computer or server
|
||||
</a>
|
||||
<a href="/docs/install">
|
||||
<b>
|
||||
|
@ -186,7 +186,7 @@
|
|||
</nav>
|
||||
|
||||
<div class="actions">
|
||||
<a href="/download" class="button secondary">Download</a>
|
||||
<a href="/download" class="button">Download</a>
|
||||
<a href="/sponsor" class="button primary">Sponsor</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
</div>
|
||||
</h1>
|
||||
|
||||
<div class="action-buttons">
|
||||
<a href="/download" class="button primary">Download</a>
|
||||
<a href="/docs/" class="button cool">Docs<sh></sh></a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="display right">
|
||||
|
@ -40,10 +44,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a href="/download" class="button primary">Download</a>
|
||||
<a href="/docs/" class="button cool">Docs<sh></sh></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
.light {
|
||||
--body-bg: white;
|
||||
--text-color: #222;
|
||||
--text-color-muted: #7087a0;
|
||||
--header-bg: rgba(118, 179, 194, 0.11);
|
||||
--header-border-color: #ebf0f2;
|
||||
--topbar-link-color-hover: black;
|
||||
|
@ -21,7 +22,8 @@
|
|||
--dropdown-link-hover-color: #142633;
|
||||
--dropdown-featured-bg: linear-gradient(to bottom, rgb(239 244 247), transparent);
|
||||
--dropdown-featured-hover-bg: rgb(223, 233, 238); /* rgb(232, 255, 254); */
|
||||
--dropdown-shadow-color: rgb(0 0 0 / .4);
|
||||
--dropdown-shadow-color: rgb(0 0 0 / .25);
|
||||
--box-bg: var(--header-border-color);
|
||||
}
|
||||
|
||||
.dark {
|
||||
|
@ -47,6 +49,7 @@
|
|||
--dropdown-featured-bg: linear-gradient(to bottom, rgb(46, 58, 66), transparent);
|
||||
--dropdown-featured-hover-bg: rgb(64, 82, 92);
|
||||
--dropdown-shadow-color: black;
|
||||
--box-bg: var(--header-bg);
|
||||
}
|
||||
|
||||
.dark #logo-light,
|
||||
|
@ -100,6 +103,16 @@ body {
|
|||
tab-size: 4;
|
||||
background-color: var(--body-bg);
|
||||
color: var(--text-color);
|
||||
background-image:
|
||||
radial-gradient(at calc(50% - min(25vw, 800px)) -10%, hsl(137.64deg, 100%, 92.42%) 0px, transparent min(15%, 500px)),
|
||||
radial-gradient(at calc(50% + min(25vw, 800px)) -10%, hsl(201.2deg, 68%, 90.2%) 0px, transparent min(15%, 500px));
|
||||
}
|
||||
|
||||
/* TODO: clean this up */
|
||||
.dark body {
|
||||
background-image:
|
||||
radial-gradient(at calc(50% - min(35vw, 700px)) -10%, hsl(129.5deg, 100%, 12.4%) 0px, transparent min(25%, 600px)),
|
||||
radial-gradient(at calc(50% + min(35vw, 700px)) -10%, hsl(201deg, 100%, 19.33%) 0px, transparent min(25%, 600px))
|
||||
}
|
||||
|
||||
main a {
|
||||
|
@ -212,7 +225,6 @@ header nav ul {
|
|||
.navbar .button {
|
||||
text-decoration: none;
|
||||
transition: all 200ms;
|
||||
color: inherit;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
@ -242,27 +254,35 @@ header nav ul {
|
|||
gap: 1em;
|
||||
}
|
||||
|
||||
button,
|
||||
.button {
|
||||
padding: .6em 1.5em;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
|
||||
/* necessary for hoversplash: */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button.primary,
|
||||
.button.primary {
|
||||
background: linear-gradient(135deg, white 25%, rgba(167, 183, 193) 80%);
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button.primary:hover,
|
||||
.button.primary:hover {
|
||||
color: #1a71cb;
|
||||
}
|
||||
|
||||
button:active,
|
||||
.button:active {
|
||||
transition: all 75ms;
|
||||
transform: scale(.95);
|
||||
|
@ -294,12 +314,14 @@ header nav ul {
|
|||
animation: 1s cubic-bezier(.16, 1, .3, 1) hoverSplash;
|
||||
}
|
||||
|
||||
.button.primary .hover-splash {
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
button .hover-splash,
|
||||
.button .hover-splash {
|
||||
background-color: rgba(24, 156, 233, 0.6);
|
||||
}
|
||||
|
||||
.button.secondary .hover-splash {
|
||||
background-color: rgba(24, 156, 233, 0.6);
|
||||
button.primary .hover-splash,
|
||||
.button.primary .hover-splash {
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
|
||||
|
@ -311,7 +333,7 @@ header nav ul {
|
|||
border-radius: 15px;
|
||||
line-height: 1.5;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 30px 75px var(--dropdown-shadow-color);
|
||||
box-shadow: 0 50px 75px var(--dropdown-shadow-color);
|
||||
visibility: hidden;
|
||||
top: calc(100% - 5px);
|
||||
left: 0;
|
||||
|
|
43
new/resources/css/docs-home.css
Normal file
43
new/resources/css/docs-home.css
Normal file
|
@ -0,0 +1,43 @@
|
|||
.quick-assist-history {
|
||||
font-size: 90%;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .5em;
|
||||
}
|
||||
|
||||
.quick-assist-history > * {
|
||||
display: inline-block;
|
||||
color: var(--text-color-muted);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.quick-assist-history > *:hover {
|
||||
color: #216688;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.quick-assist-history > :not(:first-child):before {
|
||||
content: '>';
|
||||
margin-right: .5em;
|
||||
display: inline-block;
|
||||
color: #809783;
|
||||
}
|
||||
|
||||
h3.quick-assist-question {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.quick-assist-options {
|
||||
margin-top: 1.5em;
|
||||
display: grid;
|
||||
gap: 1em;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.quick-assist button,
|
||||
.quick-assist .button {
|
||||
font-size: 100%;
|
||||
min-height: 3.5em;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
:root, .light {
|
||||
--header-bg: white;
|
||||
--button-secondary-color: rgb(64, 131, 153);
|
||||
--button-secondary-border-color: rgb(198, 217, 223);
|
||||
--button-secondary-color-hover: rgb(7, 86, 134);
|
||||
--button-secondary-border-color-hover: rgb(155, 191, 213);
|
||||
--header-bg: transparent;
|
||||
--button-color: rgb(64, 131, 153);
|
||||
--button-border-color: rgb(198, 217, 223);
|
||||
--button-color-hover: rgb(7, 86, 134);
|
||||
--button-border-color-hover: rgb(155, 191, 213);
|
||||
--nav-current-bg: linear-gradient(to right, #ecf1f3, transparent);
|
||||
--nav-link-hover-shadow-color: rgba(0, 0, 0, 0.15);
|
||||
--nav-link-hover-before-bg: #d2e5e7;
|
||||
|
@ -16,10 +16,10 @@
|
|||
|
||||
.dark {
|
||||
--header-bg: rgba(44, 130, 164, 0.11);
|
||||
--button-secondary-color: rgb(36, 166, 208);
|
||||
--button-secondary-border-color: rgb(38, 116, 140);
|
||||
--button-secondary-color-hover: rgb(0, 194, 255);
|
||||
--button-secondary-border-color-hover: rgb(0, 194, 255);
|
||||
--button-color: rgb(36, 166, 208);
|
||||
--button-border-color: rgb(38, 116, 140);
|
||||
--button-color-hover: rgb(0, 194, 255);
|
||||
--button-border-color-hover: rgb(0, 194, 255);
|
||||
--nav-current-bg: linear-gradient(to right, #1a3c4d, transparent);
|
||||
--nav-link-hover-shadow-color: rgba(255, 255, 255, 0.15);
|
||||
--nav-link-hover-before-bg: #32494f;
|
||||
|
@ -50,21 +50,27 @@ header {
|
|||
.topbar {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
button,
|
||||
.button {
|
||||
color: var(--button-color);
|
||||
border: 1px solid var(--button-border-color);
|
||||
}
|
||||
button:hover,
|
||||
.button:hover {
|
||||
color: var(--button-color-hover);
|
||||
border: 1px solid var(--button-border-color-hover);
|
||||
}
|
||||
button.primary,
|
||||
.button.primary {
|
||||
background: linear-gradient(135deg, #7ece98 25%, rgb(49, 155, 208) 80%);
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
button.primary:hover,
|
||||
.button.primary:hover {
|
||||
color: white;
|
||||
}
|
||||
.button.secondary {
|
||||
color: var(--button-secondary-color);
|
||||
border: 1px solid var(--button-secondary-border-color);
|
||||
}
|
||||
.button.secondary:hover {
|
||||
color: var(--button-secondary-color-hover);
|
||||
border: 1px solid var(--button-secondary-border-color-hover);
|
||||
}
|
||||
|
||||
|
||||
main {
|
||||
|
@ -86,8 +92,12 @@ main {
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
.docs nav {
|
||||
.docs nav,
|
||||
#pagenav {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.docs nav {
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
|
@ -98,6 +108,9 @@ main {
|
|||
display: none;
|
||||
}
|
||||
|
||||
#pagenav .heading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -240,6 +253,7 @@ article {
|
|||
|
||||
max-width: 1100px;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -248,7 +262,7 @@ 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 > :not(.fullwidth, .fullspan),
|
||||
article > .fullwidth > *,
|
||||
.pad {
|
||||
padding-left: 8%;
|
||||
|
@ -579,9 +593,54 @@ td code {
|
|||
}
|
||||
|
||||
|
||||
.box {
|
||||
border-radius: 10px;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
font-size: 18px;
|
||||
border: 2px solid var(--box-bg);
|
||||
}
|
||||
|
||||
.box-filled {
|
||||
border: none;
|
||||
background: var(--box-bg);
|
||||
}
|
||||
|
||||
.box-capped {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.box-capped > * {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.box-cap {
|
||||
border-bottom: 1px solid var(--box-bg);
|
||||
}
|
||||
|
||||
.box-filled .box-cap {
|
||||
border-bottom: 1px solid var(--button-border-color); /* #d0dfe6; */
|
||||
}
|
||||
|
||||
.box > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.box > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.box:not(.box-capped) > :first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
.box:not(.box-capped) > :last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.box h3 {
|
||||
font-size: 125%;
|
||||
margin: 0 0 .5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
#autonav {
|
||||
|
|
|
@ -11,20 +11,20 @@
|
|||
padding: 100px 0;
|
||||
}
|
||||
|
||||
.button.secondary {
|
||||
.button {
|
||||
color: rgb(54 206 255);
|
||||
border: 1px solid rgb(54 206 255);
|
||||
}
|
||||
|
||||
.button.secondary:hover {
|
||||
.button:hover {
|
||||
color: white;
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
|
||||
.button.cool {
|
||||
position: relative;
|
||||
color: rgb(226 254 214);
|
||||
border: none;
|
||||
|
||||
/* necessary for gradient dropshadow: */
|
||||
transform-style: preserve-3d;
|
||||
|
|
|
@ -105,7 +105,7 @@ function nextTheme() {
|
|||
}
|
||||
|
||||
// hoversplash effect!
|
||||
on('mouseover', '.button', (e) => {
|
||||
on('mouseover', '.button:not(.cool), button:not(.cool)', (e) => {
|
||||
const elem = document.createElement('span');
|
||||
elem.classList.add('hover-splash');
|
||||
|
||||
|
|
448
new/resources/js/docs-home.js
Normal file
448
new/resources/js/docs-home.js
Normal file
|
@ -0,0 +1,448 @@
|
|||
quickAssist = function() {
|
||||
let history = [];
|
||||
|
||||
const states = {
|
||||
start: {
|
||||
prompt: "What are you looking for?",
|
||||
options: [
|
||||
{
|
||||
text: "How to install Caddy",
|
||||
next: "install"
|
||||
},
|
||||
{
|
||||
text: "Help configuring Caddy",
|
||||
next: "configure"
|
||||
},
|
||||
{
|
||||
text: "A solution to a problem",
|
||||
next: "solution"
|
||||
},
|
||||
{
|
||||
text: "An example for my use case",
|
||||
next: "example"
|
||||
}
|
||||
]
|
||||
},
|
||||
install: {
|
||||
prompt: "How do you want to install Caddy?",
|
||||
options: [
|
||||
{
|
||||
text: "OS package manager",
|
||||
next: "install_pkgmgr"
|
||||
},
|
||||
{
|
||||
text: "Docker",
|
||||
next: "install_docker"
|
||||
},
|
||||
{
|
||||
text: "Build from source",
|
||||
next: "install_build"
|
||||
},
|
||||
{
|
||||
text: "Build with plugins",
|
||||
next: "install_with_plugins"
|
||||
},
|
||||
{
|
||||
text: "Pre-built binary",
|
||||
next: "install_binary"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_pkgmgr: {
|
||||
prompt: "Which OS are you using?",
|
||||
options: [
|
||||
{
|
||||
text: "Linux (Debian, Ubuntu, Raspbian)",
|
||||
next: "install_dpkg"
|
||||
},
|
||||
{
|
||||
text: "Linux (Fedora, RedHat, CentOS)",
|
||||
next: "install_rpm"
|
||||
},
|
||||
{
|
||||
text: "Linux (Arch, Manjaro, Parabola)",
|
||||
next: "install_arch"
|
||||
},
|
||||
{
|
||||
text: "macOS",
|
||||
next: "install_mac"
|
||||
},
|
||||
{
|
||||
text: "Windows",
|
||||
next: "install_windows"
|
||||
},
|
||||
{
|
||||
text: "Nix/NixOS",
|
||||
next: "install_nix"
|
||||
},
|
||||
{
|
||||
text: "Android",
|
||||
next: "install_android"
|
||||
},
|
||||
{
|
||||
text: "Other",
|
||||
next: "install_other"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_dpkg: {
|
||||
title: "Install Caddy on Debian-based systems",
|
||||
content: `<pre><code class="cmd"><span class="bash">sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https</span>
|
||||
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg</span>
|
||||
<span class="bash">curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list</span>
|
||||
<span class="bash">sudo apt update</span>
|
||||
<span class="bash">sudo apt install caddy</span></code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#debian-ubuntu-raspbian"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_rpm: {
|
||||
title: "Install Caddy via RPM",
|
||||
content: `<pre><code class="cmd"><span class="bash">dnf install 'dnf-command(copr)'</span>
|
||||
<span class="bash">dnf copr enable @caddy/caddy</span>
|
||||
<span class="bash">dnf install caddy</span></code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#fedora-redhat-centos"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_arch: {
|
||||
title: "Install Caddy on Arch/Manjaro/Parabola Linux",
|
||||
content: `<pre><code class="cmd"><span class="bash">pacman -Syu caddy</span></code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#arch-linux-manjaro-parabola"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_mac: {
|
||||
title: "Install Caddy on macOS",
|
||||
content: `<pre><code class="cmd bash">brew install caddy</code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#homebrew"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_windows: {
|
||||
title: "Install Caddy on Windows",
|
||||
content: `<p>Chocolatey:</p> <pre><code class="cmd">choco install caddy</code></pre>
|
||||
<p>Scoop:</p> <pre><code class="cmd">scoop install caddy</code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#windows"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_nix: {
|
||||
title: "Install Caddy on Nix/Nixpkgs/NixOS",
|
||||
content: `<ul>
|
||||
<li>Package name: <a href="https://search.nixos.org/packages?channel=unstable&show=caddy&query=caddy"><code>caddy</code></a></li>
|
||||
<li>NixOS module: <a href="https://search.nixos.org/options?channel=unstable&show=services.caddy.enable&query=services.caddy"><code>services.caddy</code></a></li>
|
||||
</ul>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#nixnixpkgsnixos"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_android: {
|
||||
title: "Install Caddy on Android",
|
||||
content: `In Termux: <pre><code class="cmd">pkg install caddy</code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#termux"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_other: {
|
||||
title: "Miscellaneous install methods",
|
||||
content: ` <h4>Webi</h2>
|
||||
<p>Linux and macOS:</p>
|
||||
<pre><code class="cmd bash">curl -sS https://webi.sh/caddy | sh</code></pre>
|
||||
<p>Windows:</p>
|
||||
<pre><code class="cmd">curl.exe https://webi.ms/caddy | powershell</code></pre>
|
||||
<h4>Ansible</h4>
|
||||
<pre><code class="cmd bash">ansible-galaxy install nvjacobo.caddy</code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#fedora-redhat-centos"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_docker: {
|
||||
title: "Official Docker image",
|
||||
content: `<pre><code class="cmd bash">docker pull caddy</code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/install#docker"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_build: {
|
||||
title: "Build Caddy from source",
|
||||
content: `<p>Make sure to have <code>git</code> and the latest version of <a href="https://go.dev">Go</a> installed.</p>
|
||||
<pre><code class="cmd"><span class="bash">git clone "https://github.com/caddyserver/caddy.git"</span>
|
||||
<span class="bash">cd caddy/cmd/caddy/</span>
|
||||
<span class="bash">go build</span></code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/build"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_with_plugins: {
|
||||
title: "Build Caddy with plugins",
|
||||
content: `
|
||||
<p>
|
||||
<code><a href="https://github.com/caddyserver/xcaddy">xcaddy</a></code> is a command line tool
|
||||
that helps you build Caddy with plugins. A basic build looks like:
|
||||
</p>
|
||||
<pre><code class="cmd bash">xcaddy build</code></pre>
|
||||
<p>
|
||||
To build with plugins, use <code>--with</code>:
|
||||
</p>
|
||||
<pre><code class="cmd bash">xcaddy build \\
|
||||
--with github.com/caddyserver/nginx-adapter
|
||||
--with github.com/caddyserver/ntlm-transport@v0.1.1</code></pre>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/build#xcaddy"
|
||||
}
|
||||
]
|
||||
},
|
||||
install_binary: {
|
||||
title: "Install Caddy binary manually",
|
||||
content: `
|
||||
<ol>
|
||||
<li>
|
||||
Obtain a Caddy binary:
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/caddyserver/caddy/releases">from releases on GitHub</a> (expand
|
||||
"Assets")
|
||||
<ul>
|
||||
<li>Refer to <a href="/docs/signature-verification">Verifying Asset Signatures</a> for how to verify
|
||||
the asset signature</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="/download">from our download page</a></li>
|
||||
<li><a href="/docs/build">by building from source</a> (either with <code>go</code> or <code>xcaddy</code>)
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/running#manual-installation">Install Caddy as a system service.</a> This is strongly recommended,
|
||||
especially for production servers.
|
||||
</li>
|
||||
</ol>
|
||||
<p>Place the binary in one of your <code>$PATH</code> (or <code>%PATH%</code> on Windows) directories so you can run
|
||||
<code>caddy</code> without typing the full path of the executable file. (Run <code>echo $PATH</code> to see the list
|
||||
of directories that qualify.)</p>
|
||||
<p>You can upgrade static binaries by replacing them with newer versions and restarting Caddy. The <a
|
||||
href="/docs/command-line#caddy-upgrade"><code>caddy upgrade</code> command</a> can make this easy.</p>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/build#xcaddy"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
configure: {
|
||||
prompt: "What are you trying to configure?",
|
||||
options: [
|
||||
{
|
||||
text: "On-demand TLS",
|
||||
next: "cfg_ondemand"
|
||||
},
|
||||
{
|
||||
text: "Authentication",
|
||||
next: "cfg_authentication"
|
||||
},
|
||||
{
|
||||
text: "Load balancing",
|
||||
next: "cfg_loadbalancing"
|
||||
}
|
||||
]
|
||||
},
|
||||
cfg_ondemand: {
|
||||
prompt: "Do you control the (DNS records of) the domain names you're serving?",
|
||||
options: [
|
||||
{
|
||||
text: "Yes",
|
||||
breadcrumb: "I control the domains",
|
||||
next: "cfg_ondemand_havecontrol"
|
||||
},
|
||||
{
|
||||
text: "No",
|
||||
breadcrumb: "DNS out of my control",
|
||||
next: "cfg_ondemand_ok"
|
||||
}
|
||||
]
|
||||
},
|
||||
cfg_ondemand_havecontrol: {
|
||||
prompt: "Do you have hundreds or thousands of your own domain names to serve?",
|
||||
options: [
|
||||
{
|
||||
text: "Yes",
|
||||
breadcrumb: "Lots of domains",
|
||||
next: "cfg_ondemand_ok"
|
||||
},
|
||||
{
|
||||
text: "No",
|
||||
breadcrumb: "Small scale",
|
||||
next: "cfg_ondemand_smallscale"
|
||||
}
|
||||
]
|
||||
},
|
||||
cfg_ondemand_smallscale: {
|
||||
title: "You likely don't need on-demand TLS.",
|
||||
content: `On-demand TLS is designed for situations when you either don't control the domain names,
|
||||
or you have too many certificates to load all at once when the server starts. For every other
|
||||
use case, standard TLS automation is likely better suited.`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/automatic-https#on-demand-tls"
|
||||
}
|
||||
]
|
||||
},
|
||||
cfg_ondemand_ok: {
|
||||
prompt: "Are you using the Caddyfile or JSON to configure Caddy?",
|
||||
options: [
|
||||
{
|
||||
text: "Caddyfile",
|
||||
next: "cfg_ondemand_caddyfile"
|
||||
},
|
||||
{
|
||||
text: "JSON",
|
||||
next: "cfg_ondemand_json"
|
||||
}
|
||||
]
|
||||
},
|
||||
cfg_ondemand_caddyfile: {
|
||||
title: "Setting up On-Demand TLS",
|
||||
content: `
|
||||
<p>In order to prevent abuse, you must first configure an <code>ask</code> endpoint so Caddy
|
||||
can check whether it should get a certificate. Add this to your global options at the top:</p>
|
||||
<pre><code>on_demand_tls {
|
||||
ask http://localhost:5555/check
|
||||
}</code></pre>
|
||||
<p>Change that endpoint to be something you've set up that will respond with HTTP 200 if the
|
||||
domain given in the <code>domain=</code> query parameter is allowed to have a certificate.</p>
|
||||
<p>Then create a site block that serves all sites/hosts on the TLS port:</p>
|
||||
<pre><code>https:// {
|
||||
tls {
|
||||
on_demand
|
||||
}
|
||||
}</code></pre>
|
||||
<p>This is the minimum config to enable Caddy to accept and service TLS connections for arbitrary
|
||||
hosts. This config doesn't invoke any handlers. Usually you'll also <code>reverse_proxy</code>
|
||||
to your backend application.</p>`,
|
||||
options: [
|
||||
{
|
||||
text: "Learn more",
|
||||
href: "/docs/automatic-https#on-demand-tls"
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
// show renders the given state into the quick assist box
|
||||
function show(state) {
|
||||
// reset & show prompt/content
|
||||
$('.quick-assist-question').innerHTML = state.prompt || state.title;
|
||||
$('.quick-assist-content').innerHTML = state.content || '';
|
||||
$('.quick-assist-options').innerHTML = '';
|
||||
|
||||
// render options
|
||||
let hasNext = false;
|
||||
if (state.options) {
|
||||
for (const opt of state.options) {
|
||||
if (opt.next) {
|
||||
hasNext = true;
|
||||
}
|
||||
const btn = document.createElement('a');
|
||||
btn.classList.add('button');
|
||||
btn.innerText = opt.text || "";
|
||||
if (opt.next) {
|
||||
btn.dataset.next = opt.next;
|
||||
btn.dataset.breadcrumb = opt.breadcrumb || opt.text;
|
||||
} else if (opt.href) {
|
||||
btn.href = opt.href;
|
||||
}
|
||||
$('.quick-assist-options').append(btn);
|
||||
}
|
||||
}
|
||||
|
||||
// if there's no "next" state, then this must be the end of
|
||||
// assistance, so show a button to reset
|
||||
if (!hasNext) {
|
||||
const reset = document.createElement('a');
|
||||
reset.classList.add('button', 'reset');
|
||||
reset.innerText = "Reset";
|
||||
$('.quick-assist-options').append(reset);
|
||||
}
|
||||
|
||||
history.push(state);
|
||||
}
|
||||
|
||||
// reset clears history and shows the start state; it does NOT delete things
|
||||
// from the UI, however.
|
||||
function reset() {
|
||||
history = [];
|
||||
show(states.start);
|
||||
}
|
||||
|
||||
// clicking breadcrumbs should take you to that point in the state machine
|
||||
on('click', '.quick-assist-history a', event => {
|
||||
// remove later breadcrumbs
|
||||
for (let sibling = event.target.nextElementSibling; sibling != null; sibling = event.target.nextElementSibling) {
|
||||
sibling.remove();
|
||||
history.pop();
|
||||
}
|
||||
|
||||
// show the state represented by the breadcrumb clicked
|
||||
if (event.target.dataset.index) {
|
||||
show(history[Number(event.target.dataset.index)]);
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
});
|
||||
|
||||
// when an option is selected, add breadcrumb and show that state
|
||||
on('click', '.quick-assist-options a[data-next]', event => {
|
||||
const link = document.createElement('a');
|
||||
link.innerText = event.target.dataset.breadcrumb || event.target.innerText;
|
||||
link.dataset.index = history.length;
|
||||
$('.quick-assist-history').append(link);
|
||||
show(states[event.target.dataset.next]);
|
||||
});
|
||||
|
||||
on('click', '.quick-assist-options a.reset', event => {
|
||||
$('.quick-assist-history a:first-child').dispatchEvent(new Event('click', { bubbles: true }));
|
||||
})
|
||||
|
||||
// when page loads, show the start of the quick assist
|
||||
reset();
|
||||
};
|
||||
|
||||
|
||||
|
||||
ready(() => {
|
||||
quickAssist();
|
||||
});
|
|
@ -11,10 +11,15 @@ ready(function() {
|
|||
}
|
||||
currentPageLink?.classList?.add('current');
|
||||
|
||||
// generate in-page nav before adding anchor links to headings
|
||||
// generate in-page nav before adding anchor links to headings;
|
||||
// only show sidebar if there are any navigable headers
|
||||
// TODO: support h3 too
|
||||
const spacingMS = 50;
|
||||
let delay = spacingMS;
|
||||
$$('main article h2').forEach(elem => {
|
||||
const h2elems = $$('main article h2');
|
||||
if (h2elems.length) {
|
||||
$('#pagenav .heading').style.display = 'block';
|
||||
h2elems.forEach(elem => {
|
||||
const a = document.createElement('a');
|
||||
a.innerText = elem.innerText;
|
||||
a.href = `#${elem.id}`;
|
||||
|
@ -23,6 +28,7 @@ ready(function() {
|
|||
}, delay);
|
||||
delay += spacingMS;
|
||||
});
|
||||
}
|
||||
|
||||
// add anchor links, inspired by https://github.com/bryanbraun/anchorjs
|
||||
$$('article > h2[id], article > h3[id], article > h4[id], article > h5[id], article > h6[id]').forEach(function(elem) {
|
||||
|
@ -84,6 +90,7 @@ ready(function() {
|
|||
});
|
||||
});
|
||||
|
||||
// toggle left-nav when menu link is clicked
|
||||
on('click', '#docs-menu', e => {
|
||||
const nav = $('#docs-menu-container');
|
||||
if (!nav.offsetHeight) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue