mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-28 09:16:50 +09:00
1 parent
ed854650f0
commit
2e8611c159
2 files changed
+24
-37
No files matched your search
@@ -38,8 +38,9 @@ values to your Headscale [configuration file](../configuration.md):
|
||||
|
||||
```yaml title="config.yaml" hl_lines="1"
|
||||
server_url: https://<SERVER_NAME>
|
||||
tls_cert_path: ""
|
||||
tls_key_path: ""
|
||||
tls:
|
||||
cert_path: ""
|
||||
key_path: ""
|
||||
```
|
||||
|
||||
Headscale logs `WRN listening without TLS but ServerURL does not start with http://` during startup. This is expected
|
||||
@@ -92,8 +93,9 @@ metrics_listen_addr: 127.0.0.1:9090
|
||||
trusted_proxies:
|
||||
- 127.0.0.1/32
|
||||
- ::1/128
|
||||
tls_cert_path: ""
|
||||
tls_key_path: ""
|
||||
tls:
|
||||
cert_path: ""
|
||||
key_path: ""
|
||||
```
|
||||
|
||||
### Apache
|
||||
|
||||
+18
-33
@@ -2,29 +2,32 @@
|
||||
|
||||
## Bring your own certificate
|
||||
|
||||
Headscale can be configured to expose its web service via TLS. To configure the certificate and key file manually, set the `tls_cert_path` and `tls_key_path` configuration parameters. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
||||
Headscale can be configured to expose its web service via TLS. To configure the certificate and key file manually, set the `tls.cert_path` and `tls.key_path` configuration parameters. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
tls_cert_path: ""
|
||||
tls_key_path: ""
|
||||
tls:
|
||||
cert_path: ""
|
||||
key_path: ""
|
||||
```
|
||||
|
||||
The certificate should contain the full chain, else some clients, like the Tailscale Android client, will reject it.
|
||||
|
||||
## Let's Encrypt / ACME
|
||||
|
||||
To get a certificate automatically via [Let's Encrypt](https://letsencrypt.org/), set `tls_letsencrypt_hostname` to the desired certificate hostname. This name must resolve to the IP address(es) headscale is reachable on (i.e., it must correspond to the `server_url` configuration parameter). The certificate and Let's Encrypt account credentials will be stored in the directory configured in `tls_letsencrypt_cache_dir`. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
||||
To get a certificate automatically via [Let's Encrypt](https://letsencrypt.org/), set `tls.acme.hostname` to the desired certificate hostname. This name must resolve to the IP address(es) headscale is reachable on (i.e., it must correspond to the `server_url` configuration parameter). The certificate and Let's Encrypt account credentials will be stored in the directory configured in `tls.acme.cache_dir`. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
tls_letsencrypt_hostname: ""
|
||||
tls_letsencrypt_listen: ":http"
|
||||
tls_letsencrypt_cache_dir: ".cache"
|
||||
tls_letsencrypt_challenge_type: HTTP-01
|
||||
tls:
|
||||
acme:
|
||||
hostname: ""
|
||||
http_listen: ":http"
|
||||
cache_dir: /var/lib/headscale/cache
|
||||
challenge_type: HTTP-01
|
||||
```
|
||||
|
||||
### Challenge types
|
||||
|
||||
Headscale only supports two values for `tls_letsencrypt_challenge_type`: `HTTP-01` (default) and `TLS-ALPN-01`.
|
||||
Headscale supports three values for `tls.acme.challenge_type`: `HTTP-01` (default), `TLS-ALPN-01` and `DNS-01`. `DNS-01` publishes the challenge through the DNS provider in `dns.challenge.provider`.
|
||||
|
||||
#### HTTP-01
|
||||
|
||||
@@ -32,9 +35,9 @@ For `HTTP-01`, headscale must be reachable on port 80 for the Let's Encrypt auto
|
||||
|
||||
!!! warning "`listen_addr` cannot also be port 80"
|
||||
|
||||
`listen_addr` and `tls_letsencrypt_listen` must not bind the same TCP socket. A common mistake is setting `listen_addr: 0.0.0.0:80` together with `tls_letsencrypt_hostname` — both endpoints try to claim port 80, and the second bind fails with `address already in use` even though no other process is involved. Headscale validates this at startup and refuses to launch with a `Fatal config error: listen_addr and tls_letsencrypt_listen would bind the same TCP socket` message. Use `listen_addr: 0.0.0.0:443` (or any non-80 port) when HTTP-01 is enabled.
|
||||
`listen_addr` and `tls.acme.http_listen` must not bind the same TCP socket. A common mistake is setting `listen_addr: 0.0.0.0:80` together with `tls.acme.hostname` — both endpoints try to claim port 80, and the second bind fails with `address already in use` even though no other process is involved. Headscale validates this at startup and refuses to launch with a `Fatal config error: listen_addr and tls.acme.http_listen would bind the same TCP socket` message. Use `listen_addr: 0.0.0.0:443` (or any non-80 port) when HTTP-01 is enabled.
|
||||
|
||||
If you need to change the ip and/or port used by headscale for the Let's Encrypt validation process, set `tls_letsencrypt_listen` to the appropriate value. This can be handy if you are running headscale as a non-root user (or can't run `setcap`). Keep in mind, however, that Let's Encrypt will _only_ connect to port 80 for the validation callback, so if you change `tls_letsencrypt_listen` you will also need to configure something else (e.g. a firewall rule) to forward the traffic from port 80 to the ip:port combination specified in `tls_letsencrypt_listen`.
|
||||
If you need to change the ip and/or port used by headscale for the Let's Encrypt validation process, set `tls.acme.http_listen` to the appropriate value. This can be handy if you are running headscale as a non-root user (or can't run `setcap`). Keep in mind, however, that Let's Encrypt will _only_ connect to port 80 for the validation callback, so if you change `tls.acme.http_listen` you will also need to configure something else (e.g. a firewall rule) to forward the traffic from port 80 to the ip:port combination specified in `tls.acme.http_listen`.
|
||||
|
||||
#### TLS-ALPN-01
|
||||
|
||||
@@ -42,12 +45,12 @@ For `TLS-ALPN-01`, headscale listens on the ip:port combination defined in `list
|
||||
|
||||
### Technical description
|
||||
|
||||
Headscale uses [autocert](https://pkg.go.dev/golang.org/x/crypto/acme/autocert), a Golang library providing [ACME protocol](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment) verification, to facilitate certificate renewals via [Let's Encrypt](https://letsencrypt.org/about/). Certificates will be renewed automatically, and the following can be expected:
|
||||
Headscale uses [CertMagic](https://github.com/caddyserver/certmagic), a Golang library providing [ACME protocol](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment) verification, to facilitate certificate renewals via [Let's Encrypt](https://letsencrypt.org/about/). Certificates will be renewed automatically, and the following can be expected:
|
||||
|
||||
- Certificates provided from Let's Encrypt have a validity of 3 months from date issued.
|
||||
- Renewals are only attempted by headscale when 30 days or less remains until certificate expiry.
|
||||
- Renewal attempts by autocert are triggered at a random interval of 30-60 minutes.
|
||||
- No log output is generated when renewals are skipped, or successful.
|
||||
- Renewals start when a third of the validity remains.
|
||||
- Renewal checks run every 10 minutes.
|
||||
- Log lines from the library are logged with `logger=acme`.
|
||||
|
||||
#### Checking certificate expiry
|
||||
|
||||
@@ -62,21 +65,3 @@ $ openssl s_client -servername [hostname] -connect [hostname]:443 | openssl x509
|
||||
notBefore=Feb 8 09:48:26 2024 GMT
|
||||
notAfter=May 8 09:48:25 2024 GMT
|
||||
```
|
||||
|
||||
#### Log output from the autocert library
|
||||
|
||||
As these log lines are from the autocert library, they are not strictly generated by headscale itself.
|
||||
|
||||
```plaintext
|
||||
acme/autocert: missing server name
|
||||
```
|
||||
|
||||
Likely caused by an incoming connection that does not specify a hostname, for example a `curl` request directly against the IP of the server, or an unexpected hostname.
|
||||
|
||||
```plaintext
|
||||
acme/autocert: host "[foo]" not configured in HostWhitelist
|
||||
```
|
||||
|
||||
Similarly to the above, this likely indicates an invalid incoming request for an incorrect hostname, commonly just the IP itself.
|
||||
|
||||
The source code for autocert can be found [here](https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.19.0:acme/autocert/autocert.go)
|
||||
Reference in new issue
Block a user