On launch, Caddy is attempting to requisition a certificate for safe.arix.com from LetsEncrypt.
2017/03/09 20:48:24 [safe.arix.com] failed to get certificate: acme: Error 400 - urn:acme:error:connection - Failed to connect to 184.108.40.206:443 for TLS-SNI-01 challenge
Indicates that the ACME server wasn’t able to make a connection to your server on port :443. Double check that your server is reachable at 220.127.116.11 and listening on :443. You could alternatively use DNS validation to bypass this check.
Caddy will exit on launch unless you resolve this issue or turn off Automatic HTTPS, there’s likely nothing wrong with the service running at :8002.
thank you. you were correct. I had many hurdles to overcome before I managed to set it up properly. at this point the error is different:
Activating privacy features...2017/03/09 22:35:11 [INFO][safe.arix.com] acme: Obtaining bundled SAN certificate
2017/03/09 22:35:11 [INFO][safe.arix.com] acme: Could not find solver for: dns-01
2017/03/09 22:35:11 [INFO][safe.arix.com] acme: Trying to solve HTTP-01
2017/03/09 22:35:11 [INFO] Received request for domain 192.168.1.67 with method GET
2017/03/09 22:35:12 [safe.arix.com] failed to get certificate: acme: Error 403 - urn:acme:error:unauthorized - The key authorization file from the server did not match this challenge [3J0FXpf2cyKnbUPqzRF0m2ys0Dut0q1__79PilObmPQ.rbQdJJTMuirfTRwAFE0eaGsLdQZvMcxeHbHsD0AK0RQ] != [TEST]
Validation for safe.arix.com:80
urn:acme:error:unauthorized - The key authorization file from the server did not match this challenge [3J0FXpf2cyKnbUPqzRF0m2ys0Dut0q1__79PilObmPQ.rbQdJJTMuirfTRwAFE0eaGsLdQZvMcxeHbHsD0AK0RQ] != [TEST]
Indicates to me that the ACME server successfully connected to 18.104.22.168:80, but the challenge response was incorrect, so the certificate request was denied.
A quick curl -I 22.214.171.124 returns:
HTTP/1.1 200 OK
Date: Fri, 10 Mar 2017 07:56:37 GMT
Content-Type: text/html; charset=UTF-8
Indicating that Caddy is not listening on that IP address and port - an Apache server is. Your DNS may be pointing at the wrong server, or your server is misconfigured such that the wrong webserver is listening on port 80.
To be unambiguous: for Caddy to request a certificate for any given domain such as example.com, a public DNS lookup must resolve example.com to an accessible IP address, and requests to that IP address on port :80 and :443 must be answered by the instance of Caddy that initiated the request.
it may be, then, that I just can’t test with my existing environment. you’re right that if you query that IP address on port 80 you’ll get my apache server, but if you query it by the right name (both www.arix.com and safe.arix.com point to the same IP address):
curl -I safe.arix.com
HTTP/1.1 503 Service Unavailable
Date: Fri, 10 Mar 2017 18:29:34 GMT
Content-Type: text/html; charset=iso-8859-1
the request gets routed by Apache to my laptop where I would have Caddy running (if I didn’t have these issues) and it would proxy the request to port 8002, where I have a listener running.
my Caddyfile asks that traffic be proxied for the name safe.arix.com but before that happens Caddy has to come up and I’m guessing that means I have to have a public IP dedicated to the host running Caddy and thus I can’t test the way I’m testing.
however when I make a request, I get a curious failure:
$ printf "GET / HTTP/1.0\n\n" |nc graph.speakr.com 80
HTTP/1.0 404 Not Found
Content-Type: text/plain; charset=utf-8
Date: Tue, 14 Mar 2017 19:57:56 GMT
No such site at :80
which brings me to my lack of understanding of Caddy. by default, it answers on port 2015, I read, unless it qualifies for encryption, in which case it listens on 443. so that means it doesn’t listen on port 80 at all, unless told to. I thought that might explain my failure but changing the server name at the top of the Caddyfile to http://graph.speakr.com didn’t fix the problem, nor does graph.speakr.com:80
so now what am I doing wrong?
p.s. in googling, I found Matt Holt’s comment “the address in the Caddyfile needs to match that in the URL” so thinking that the actual url might include the trailing / (since, after all, I’m GETting /), I tried graph.speakr.com/ - but that didn’t work either
2017/03/14 20:25:05 http: TLS handshake error from 126.96.36.199:55223: tls: unsupported SSLv2 handshake received
2017/03/14 20:25:36 http: TLS handshake error from 188.8.131.52:55297: tls: client offered an unsupported, maximum protocol version of 300
2017/03/14 20:26:35 http: TLS handshake error from 184.108.40.206:55448: tls: client offered an unsupported, maximum protocol version of 301
and I don’t get a prompt so I can’t actually make a request
some more progress. after reading about issues with protocol negotiation using certain clients it occurred to me to upgrade my openssl library. I use brew on OSX and discovered that /usr/bin/openssl is left unaffected by brew upgrades. the correct location is /usr/local/Cellar/openssl/1.0.2k/bin/openssl and using the new version I get a proper connection:
however, I thought piping a command to openssl would actually send the request. nowhere in the output do I see the document I requested, but if I manually type it in, I get routed properly (so it works).
so my question at this point is: why do I have to declare both ports (80 & 443) for this to work instead of just declaring the host name as I was doing originally?
if I (making the calls properly with HTTP 1.1) call it when it’s just defined with the name, I get:
HTTP/1.1 301 Moved Permanently
Date: Tue, 14 Mar 2017 21:20:22 GMT
Content-Type: text/html; charset=utf-8
Wow, you’ve been busy! I’ll try answer what I can.
That 503 from Apache implies to me that your upstream is misconfigured in Apache or it is otherwise unable to communicate with Caddy (at all). If Apache could connect to Caddy, but Caddy was playing up, Apache would have given you a status 502 instead, I believe.
Not to put too fine a point on it, no, that’s not strictly required. All that needs to happen is that a request to example.com's IP address, for example.com, needs to be responded to by Caddy. You can absolutely put a proxy in between, as long as the proxy faithfully forwards the request to Caddy and returns Caddy’s response to the client.
Again, not necessarily - see previous. As long as the proxy is set up correctly and faithfully (and transparently edit: actually, transparency is not required either; all LetsEncrypt actually cares about is that the well-known token they request matches what they told Caddy to put there) proxying, it should work.
With this command, you’re not actually indicating the server name (graph.speakr.com) to the server, you’re just connecting to the server (by IP address as nc simply resolves the FQDN) on port 80 and sending GET / HTTP/1.0. Caddy doesn’t have a matching server name, as you have not configured a default server ("" != graph.speakr.com - you would need to set up a blanket vhost :80 to catch these kinds of requests). Instead of printf | nc, try curl -I https://graph.speakr.com, which will correctly indicate the server name to Caddy.
Well and good, but you’re testing a few times using unsupported protocols. The tls directive can be used to extend the protocol support range. Caddy will close the connection on unsupported protocols.
The effective change here is that you’re indicating the server name; you could revert your Caddyfile change and make this request again, and the expected behaviour would be a 301 in response (telling you to try HTTPS on port 443 instead), with A HTTPS request returning status 200.
Again, I recommend relying on curl -I instead of piping printf to nc.
You absolutely can. Specifying :80 will disable Automatic HTTPS and only serve HTTP, specifying :443 will disable HTTP (but leave certificate management running), and specifying both separately is a common method of getting fine grained control over the redirection process where required (by default it simply 301’s to HTTPS).
This is expected behaviour, which is good! Automatic HTTPS with just the name declared will set up the listeners on :80 (where it will issue 301 redirects to HTTPS) as well as :443 (where it will serve the actual site, as per your server directives).