0
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-30 22:34:15 -05:00
Commit graph

127 commits

Author SHA1 Message Date
Matthew Holt
b699a17a1b
tls: Fix OCSP stapling bug when certificate names overlap other certs
https://caddy.community/t/random-ocsp-response-errors-for-random-clients/2473?u=matt

Certificates are keyed by name in the cache, optimized for fast lookups
during TLS handshakes using SNI. A more "correct" way that is truly a
1:1 would be to cache certificates by a hash of the leaf's DER bytes,
but this involves an extra index to maintain. So instead of that, we
simply choose to prevent overlap when keying certificates by server
name. This avoids the ambiguity when updating OCSP staples, for instance.
2017-08-12 00:12:22 -06:00
Jason Hutchinson
f3721c103c tls: add optional 'ca' tls directive, closes #1689 (#1699) 2017-06-24 11:10:44 -07:00
bamling
a368230ba5 caddytls: introduced own ChallengeProvider type to fix imports related to vendor (#1700)
* introduced own ChallengeProvider type, based on acme.ChallengeProvider to avoid vendoring/version mismatches in Caddy plugins; see Caddy issue #1697

* fixed up comments for ChallengeProvider

* moved ChallengeProvider to caddytls/tls.go
2017-06-06 09:23:00 -06:00
Matthew Holt
410ece831f tls: Only require renewed cert at startup 7 days out (issue #1680) 2017-05-19 08:30:01 -06:00
Andrew Steinborn
b0cf3f0d2d tls: Prefer ChaCha20 if AES-NI instruction set is unavailable (#1675)
Fixes #1674
2017-05-17 10:45:17 -06:00
Aaron Ellington
7ee4ea244f lint fixes 2017-04-29 20:53:58 -04:00
Matthew Holt
705cb98865 Remove TODO because Let's Encrypt has fixed issuance/OCSP ordering 2017-04-29 16:49:07 -06:00
Jonas Östanbäck
91da965a39 Disable warning for insecure CA if located on private network. (#1599)
* Disable warning for insecure CA if located on private network.
 * Add IsPrivateNetwork function
 * Add tests

Signed-off-by: Jonas Östanbäck <jonas.ostanback@gmail.com>

* Add more testcases

Signed-off-by: Jonas Östanbäck <jonas.ostanback@gmail.com>

* Rename IsPrivateNetwork -> IsInternal

Signed-off-by: Jonas Östanbäck <jonas.ostanback@gmail.com>
2017-04-20 05:38:54 -06:00
Matthew Holt
ac3bbdbd3f
tls: Arrange cipher suites in map in preference order for convenience
Maps are NOT ordered at runtime but I still want the cipher suites
listed in order of preference in the source file for convenience.
2017-04-17 22:11:05 -06:00
Matthew Holt
d85e90a7b4
tls: Only update OCSP staple if field is not nil (fixes #1514) 2017-03-13 09:30:58 -06:00
Matt Holt
52584f7f23 Merge pull request #1499 from mholt/issue1394
Log certificate location
2017-03-09 17:45:06 -07:00
Matthew Holt
6bc3e7536e
tls: Command line flags to disable HTTP and TLS-SNI challenges
This could have just as easily been a tls directive property in the
Caddyfile, but I figure if these challenges are being disabled, it's
because of port availability or process privileges, both of which would
affect all sites served by this process. The names of the flag are long
but descriptive.

I've never needed this but I hear of quite a few people who say they
need this ability, so here it is.
2017-03-08 00:06:49 -07:00
Matthew Holt
e3f2d96a5e
httpserver: Flags to customize HTTP and HTTPS ports (incl. for ACME)
This commit removes _almost_ all instances of hard-coded ports 80 and
443 strings, and now allows the user to define what the HTTP and HTTPS
ports are by the -http-port and -https-ports flags.

(One instance of "80" is still hard-coded in tls.go because it cannot
import httpserver to get access to the HTTP port variable. I don't
suspect this will be a problem in practice, but one workaround would be
to define an exported variable in the caddytls package and let the
httpserver package set it as well as its own HTTPPort variable.)

The port numbers required by the ACME challenges HTTP-01 and TLS-SNI-01
are hard-coded into the spec as ports 80 and 443 for good reasons,
but the big question is whether they necessarily need to be the HTTP
and HTTPS ports. Although the answer is probably no, they chose those
ports for convenience and widest compatibility/deployability. So this
commit also assumes that the "HTTP port" is necessarily the same port
on which to serve the HTTP-01 challenge, and the "HTTPS port" is
necessarily the same one on which to serve the TLS-SNI-01 challenge. In
other words, changing the HTTP and HTTPS ports also changes the ports
the challenges will be served on.

If you change the HTTP and HTTPS ports, you are responsible for
configuring your system to forward ports 80 and 443 properly.

Closes #918 and closes #1293. Also related: #468.
2017-03-06 18:18:49 -07:00
Toby Allen
bcddfb2daa Log certificate location 2017-03-06 21:56:24 +00:00
Matt Holt
73794f2a2c tls: Refactor internals related to TLS configurations (#1466)
* tls: Refactor TLS config innards with a few minor syntax changes

muststaple -> must_staple
"http2 off" -> "alpn" with list of ALPN values

* Fix typo

* Fix QUIC handler

* Inline struct field assignments
2017-02-21 09:49:22 -07:00
Mateusz Gajewski
1262ae92e9 Disable TLS completely if there is no listener with tls enabled (#1456)
* Disable TLS completely if there is no listener with tls enabled

* Format code
2017-02-19 08:09:35 -07:00
Mateusz Gajewski
286d8d1e89 tls: Per-site TLS configs using GetClientConfig, including http2 switch (#1389)
* Remove manual TLS clone method

* WiP tls

* Use GetClientConfig for tls.Config

* gofmt -s -w

* GetConfig

* Handshake

* Removed comment

* Disable HTTP2 on demand

* Remove junk

* Remove http2 enable (no-op)
2017-02-18 15:26:23 -07:00
elcore
579007822f Add support for ChaCha20-Poly1305 (#1443) 2017-02-16 22:16:29 -07:00
elcore
91ff734327 Implement curve X25519 (Golang 1.8) (#1376)
* Implement curve X25519

* caddytls: Added a default curves list

* caddytls: Improve tests
2017-02-16 17:19:58 -07:00
Matt Holt
58b2edd229 Merge pull request #1354 from mholt/keyrotationfix
Set session ticket keys properly (fixed in Go 1.8)
2017-02-16 16:43:02 -07:00
Matthew Holt
11adb2e5a7
tls: Always stop and report cert renewal error if operator is present 2017-01-21 15:14:04 -07:00
Matthew Holt
0e34c7c970
tls: Fix background certificate renewals that use TLS-SNI challenge
The loop which performs renewals in the background obtains a read lock
on the certificate cache map, so that it can be safely iterated. Before
this fix, it would obtain the renewals in the read lock. This has been
fine, except that the TLS-SNI challenge, when invoked after Caddy has
already started, requires adding a certificate to the cache. Doing this
requires an exclusive write lock. But it cannot obtain a write lock
because a read lock is obtained higher in the stack, while the loop
iterates. In other words, it's a deadlock.

I was able to reproduce this issue consistently locally, after jumping
through many hoops to force a renewal in a short time that bypasses
Let's Encrypt's authz caching. I was also able to verify that by queuing
renewals (like we do deletions and OCSP updates), lock contention is
relieved and the deadlock is avoided.

This only affects background renewals where the TLS-SNI(-01) challenge
are used. Users report seeing strange errors in the logs after this
happens ("tls: client offered an unsupported, maximum protocol version
of 301"), but I was not able to reproduce these locally. I was also not
able to reproduce the leak of sockets which are left in CLOSE_WAIT.
I am not sure if those are symptoms of running in production on Linux
and are related to this bug, or not.

Either way, this is an important fix. I do not yet know the ripple
effects this will have on other symptoms we've been chasing. But it
definitely resolves a deadlock during renewals.
2017-01-21 14:39:36 -07:00
Matthew Holt
c6ba43f888
Set session ticket keys properly (fixed in Go 1.8) 2017-01-15 09:30:02 -07:00
Ben Gadbois
eee9d00255 Fix small misspellings 2017-01-10 13:09:24 -08:00
Matthew Holt
e641d2fd65
Set listenHost to localhost if empty; fixes test on Windows 2016-12-23 10:28:00 -07:00
Matthew Holt
1da70d3ba1
ACME challenge proxy now accounts for ListenHost (bind); fixes #1296 2016-12-23 09:40:03 -07:00
Matthew Holt
80eb45fcfb
tls: Improve flaky test depending on CPU scheduling (I think) 2016-11-28 23:37:22 -07:00
elcore
53e117802f Add support for OCSP Must-Staple for Let's Encrypt certs (#1221)
* Fix Caddytls

* Let the user decide

* Address comments
2016-10-29 08:44:49 -06:00
Mateusz Gajewski
8cc3416bbc
Remove dead code, do struct alignment, simplify code 2016-10-25 19:19:54 +02:00
elcore
8561f42786 CurvePreferences (Test) (#1161)
We need consistency in code style!!!
2016-10-04 01:15:23 +02:00
elcore
e1ea58b7c4 Customize curve preferences, closes #1117 (#1159)
* Feature Request: #1117

* The order of the curves matter
2016-10-03 10:52:45 -06:00
Matthew Holt
b766dab9fa
tls: Reorder some logic to avoid subtle, undocumented behavior
By calling SetTLSAddress, the acme package reset the challenge provider
to the default one instead of keeping the custom one we specified before
with SetChallengeProvider. Yikes. This means that Caddy would try to
open a listener on port 443 even though we should have been handling it
with our provider, causing the challenge to fail, since usually port 443
is in use.

So this change just reorders the calls so that our provider takes
precedence.

cf. https://github.com/xenolf/lego/pull/292
2016-09-28 18:29:46 -06:00
Matthew Holt
8ecd543519
Refactor and improve TLS storage code (related to locking) 2016-09-19 17:24:34 -06:00
Matthew Holt
bedad34b25
Clean up some significant portions of the TLS management code 2016-09-14 22:30:49 -06:00
Matthew Holt
7ef405f9b2
Satisfy gofmt 2016-09-08 20:32:21 -06:00
Matthew Holt
11bf28f783
Weird, git didn't commit this closing curly brace 2016-09-08 18:54:36 -06:00
Matthew Holt
98bba33861 Lower-case server name for good measure
This already happens in the getCertificate function, but doing it here
guarantees case insensitivity across the board for this handshake.
2016-09-08 18:50:04 -06:00
Matthew Holt
abdf13ea30 Improve TLS storage provider errors
We renamed caddytls.ErrStorageNotFound to caddytls.ErrNotExist to more
closely mirror the os package. We changed it to an interface wrapper
so that the custom error message can be preserved. Returning only "data
not found" was useless in debugging because we couldn't know the
concrete value of the error (like what it was trying to load).

Users can do a type assertion to determine if the error value is a "not
found" error instead of doing an equality check.
2016-09-08 18:50:04 -06:00
Matthew Holt
a251831feb Fix bug renewing certs affecting Caddyfiles using wildcard addresses
A Caddyfile using *.example.com as its site address would be subject to
this bug at renewal time, as it would use the literal "*.example.com"
value instead of the name being passed in to obtain a certificate.
This change fixes the LoadSite call so that it looks in the proper
directory for the certificate resources.
2016-09-08 18:50:04 -06:00
Matthew Holt
5f135a27d5
Eliminate ineffectual assignments
Most of these were fixed by handling errors that were previously
unhandled (oops).
2016-09-05 10:30:46 -06:00
Matthew Holt
45a3d0b526
Fix misspellings 2016-09-05 10:20:34 -06:00
Matthew Holt
14a6e4b4ed
More minor text fixes 2016-08-30 13:37:35 -06:00
Matthew Holt
34a99598f7
Ignore conflicting settings if TLS disabled (fixes #1075) 2016-08-26 16:18:08 -06:00
Matthew Holt
b1ae8a71f1
More tests for TLS configuration 2016-08-25 17:13:27 -06:00
Filippo Valsorda
ef58536711 Actually set tls.Config.PreferServerCipherSuites
It was set by default on the caddy-internal config object, and even
checked for conflicts, but it was never actually reflected on the
tls.Config.

This will have user-visible changes: a client that prefers, say, AES-CBC
but also supports AES-GCM would have used AES-CBC befor this, and will
use AES-GCM after.

This is desirable and important behavior, because if for example the
server wanted to support 3DES, but *only if it was strictly necessary*,
it would have had no way of doing so with PreferServerCipherSuites
false, as the client preference would have won.
2016-08-25 18:28:51 +01:00
Matthew Holt
151d0baa94
Minor text fixes ;) 2016-08-23 15:47:23 -06:00
Luna Duclos
1dfe1e5ada Add plugin capabilities for tls storage.
To use a plugged in storage, specify "storage storage_name" in the tls block of the Caddyfile, by default, file storage will be used
2016-08-23 23:00:20 +02:00
Matthew Holt
628920e20e
Improve logic related to error handling on SiteExists call
No need to check if SiteExists if the config is not managed or the name
does not even qualify.
2016-08-23 14:51:07 -06:00
Matt Holt
1d3212a598 Merge pull request #1046 from PalmStoneGames/master
Add error parameter to storage.SiteExists()
2016-08-20 16:52:18 -06:00
Matthew Holt
c75ee0000e
Fix edge case in stapling; do not allow certs without any names 2016-08-19 13:42:48 -06:00
Luna Duclos
78341a3a9a Add error parameter to storage.SiteExists() 2016-08-18 18:38:33 +02:00
Matthew Holt
454b1e3939
Honor bind directive for ACME challenges
Fixes https://forum.caddyserver.com/t/basic-caddy-installation-failing-on-automatic-https/472?u=matt
2016-08-15 12:08:51 -06:00
Matthew Holt
46bc0d5c4e
Whoops, finishing up the last commit properly
Need to add the name to namesObtaining each time we use the ACME client.
2016-08-10 23:44:43 -06:00
Matthew Holt
8e75ae2495
Only consume HTTP challenge for names we are solving for (closes #549)
If another ACME client is trying to solve a challenge for a name not
being served by Caddy on the same machine where Caddy is running, the
HTTP challenge will be consumed by Caddy rather than allowing the owner
to use the Caddyfile to proxy the challenge.

With this change, we only consume requests for HTTP challenges for
hostnames that we recognize. Before doing the challenge, we add the
name to a set, and when seeing if we should proxy the challenge, we
first check the path of course to see if it is an HTTP challenge;
if it is, we then check that set to see if the hostname is in the
set. Only if it is, do we consume it.

Otherwise, the request is treated like any other, allowing the owner
to configure a proxy for such requests to another ACME client.
2016-08-10 22:13:06 -06:00
Matthew Holt
e081d8b5c2
Maintainence routine deletes old (expired) OCSP staple files 2016-08-09 16:46:51 -06:00
Matthew Holt
8eefeb6788
Begin improved OCSP stapling by persisting staple to disk 2016-08-09 16:12:22 -06:00
Shawn Smith
0f04f2fd44 fix typo 2016-08-09 14:57:17 +09:00
elcore
4b3c532573 Use P384 for TestUser (privateKey) (#1009) 2016-08-08 11:13:10 -06:00
elcore
e5a8927635 Allow just one TLS Protocol (Caddyfile) (#1004)
* Allow just one TLS Protocol

* Fix typo
2016-08-06 15:00:54 -06:00
Matthew Holt
0d8b95334f
Use Let's Encrypt's permalink to subscriber agreement 2016-08-06 14:42:00 -06:00
Tw
3d43c5b697 tls: fix TestStandaloneTLSTicketKeyRotation data race
==================
WARNING: DATA RACE
Write at 0x00c42049d300 by goroutine 26:
  github.com/mholt/caddy/caddytls.standaloneTLSTicketKeyRotation()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto.go:230 +0x698

Previous read at 0x00c42049d300 by goroutine 25:
  github.com/mholt/caddy/caddytls.TestStandaloneTLSTicketKeyRotation()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto_test.go:113 +0x413
  testing.tRunner()
      /home/tw/goroot/src/testing/testing.go:610 +0xc9

Goroutine 26 (running) created at:
  github.com/mholt/caddy/caddytls.TestStandaloneTLSTicketKeyRotation()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto_test.go:101 +0x2a4
  testing.tRunner()
      /home/tw/goroot/src/testing/testing.go:610 +0xc9

Goroutine 25 (running) created at:
  testing.(*T).Run()
      /home/tw/goroot/src/testing/testing.go:646 +0x52f
  testing.RunTests.func1()
      /home/tw/goroot/src/testing/testing.go:793 +0xb9
  testing.tRunner()
      /home/tw/goroot/src/testing/testing.go:610 +0xc9
  testing.RunTests()
      /home/tw/goroot/src/testing/testing.go:799 +0x4b5
  testing.(*M).Run()
      /home/tw/goroot/src/testing/testing.go:743 +0x12f
  github.com/mholt/caddy/caddytls.TestMain()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/setup_test.go:27 +0x133
  main.main()
      github.com/mholt/caddy/caddytls/_test/_testmain.go:116 +0x1b1
==================
==================
WARNING: DATA RACE
Write at 0x00c4204aa6c0 by goroutine 26:
  github.com/mholt/caddy/caddytls.TestStandaloneTLSTicketKeyRotation.func2()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto_test.go:93 +0x56
  github.com/mholt/caddy/caddytls.standaloneTLSTicketKeyRotation()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto.go:233 +0x638

Previous read at 0x00c4204aa6c0 by goroutine 25:
  github.com/mholt/caddy/caddytls.TestStandaloneTLSTicketKeyRotation()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto_test.go:108 +0x391
  testing.tRunner()
      /home/tw/goroot/src/testing/testing.go:610 +0xc9

Goroutine 26 (running) created at:
  github.com/mholt/caddy/caddytls.TestStandaloneTLSTicketKeyRotation()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/crypto_test.go:101 +0x2a4
  testing.tRunner()
      /home/tw/goroot/src/testing/testing.go:610 +0xc9

Goroutine 25 (running) created at:
  testing.(*T).Run()
      /home/tw/goroot/src/testing/testing.go:646 +0x52f
  testing.RunTests.func1()
      /home/tw/goroot/src/testing/testing.go:793 +0xb9
  testing.tRunner()
      /home/tw/goroot/src/testing/testing.go:610 +0xc9
  testing.RunTests()
      /home/tw/goroot/src/testing/testing.go:799 +0x4b5
  testing.(*M).Run()
      /home/tw/goroot/src/testing/testing.go:743 +0x12f
  github.com/mholt/caddy/caddytls.TestMain()
      /home/tw/golib/src/github.com/mholt/caddy/caddytls/setup_test.go:27 +0x133
  main.main()
      github.com/mholt/caddy/caddytls/_test/_testmain.go:116 +0x1b1
==================

Signed-off-by: Tw <tw19881113@gmail.com>
2016-08-02 15:28:12 +08:00
Matthew Holt
c8daaba4be
Update link to SA 1.1.1 (and other minor tweaks) 2016-07-28 11:11:14 -06:00
Matthew Holt
af48bbd234
Scope TLS max_certs to site config instead of global 2016-07-28 11:08:18 -06:00
Matthew Holt
b35d19d78e Set protocol version properly (fixes #943) 2016-07-19 11:48:44 -06:00
Matthew Holt
aede4ccbce Small changes; mostly comments 2016-07-18 14:32:28 -06:00
Matthew Holt
502a8979a8 Propagate DNS provider plugins to caddy package so -plugins shows them 2016-07-15 21:29:06 -06:00
Chad Retz
88a2811e2a Pluggable TLS Storage (#913)
* Initial concept for pluggable storage (sans tests and docs)

* Add TLS storage docs, test harness, and minor clean up from code review

* Fix issue with caddymain's temporary moveStorage

* Formatting improvement on struct array literal by removing struct name

* Pluggable storage changes:

* Change storage interface to persist all site or user data in one call
* Add lock/unlock calls for renewal and cert obtaining

* Key fields on composite literals
2016-07-08 07:32:31 -06:00
Matthew Holt
80dd95a495
Change outreq.Host instead of r.Host (possibly related to #874)
Also a few little formatting changes and comments.
2016-06-28 18:19:35 -06:00
Matthew Holt
937654d1e0 Set host and port on address if specified via flag (fixes #888)
Also fixed a few typos and renamed caddyfile.ServerBlocks() to
caddyfile.Parse().
2016-06-20 18:25:42 -06:00
Matthew Holt
1fdc46e571
Fix tests after controller refactor
The search-and-replace was a little too aggressive and I accidentally
ran tests recursively in a subdirectory instead of repo's top folder.
2016-06-20 12:29:19 -06:00
Matthew Holt
a798e0c951 Refactor how caddy.Context is stored and used
- Server types no longer need to store their own contexts; they are
  stored on the caddy.Instance, which means each context will be
  properly GC'ed when the instance is stopped. Server types should use
  type assertions to convert from caddy.Context to their concrete
  context type when they need to use it.
- Pass the entire context into httpserver.GetConfig instead of only the
  Key field.
- caddy.NewTestController now requires a server type string so it can
  create a controller with the proper concrete context associated with
  that server type.

Tests still need more attention so that we can test the proper creation
of startup functions, etc.
2016-06-20 11:59:23 -06:00
Matthew Holt
2b06edccd3
Use challenge domain for tls-sni solver
Matches the new upstream function signature and fixes previously broken
behavior; new solver code confirmed to work during restarts
2016-06-13 17:48:59 -06:00
Matthew Holt
daa4de572e
Ensure certificate has a non-nil config when caching (fixes #875)
Also we change the scheme of the site's address if TLS is enabled and
no other scheme is explicitly set; this makes it appear as "https" when
we print it; otherwise it would show "http" when TLS is turned on
implicitly, and that is confusing/incorrect.
2016-06-09 19:12:11 -06:00
Matthew Holt
e7fc26e3fb
Improved godoc, added two missing directives, update change log 2016-06-07 09:27:14 -06:00
Matthew Holt
d3860f95f5
Make RegisterPlugin() more consistent, having name as first argument 2016-06-06 15:31:03 -06:00
Matthew Holt
2f92443de7
More tests, several fixes and improvements; export caddyfile.Token
We now sneakily chain in the errors directive if gzip is present but
not errors. This change fixes #616.
2016-06-04 22:50:23 -06:00
Matthew Holt
ac4fa2c3a9
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.

The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.

The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.

The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.

Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.

A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).

Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.

Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.

Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.

I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 17:00:29 -06:00