Nginx: Difference between revisions

m Add a raw html test example
Add a Private Local LAN Server Example
Line 266: Line 266:
The nginx module for NixOS has native support for Let's Encrypt certificates;  {{nixos:option|services.nginx.+acme}}. The {{manual:nixos|sec=#module-security-acme-nginx|chapter=Chapter 20. SSL/TLS Certificates with ACME}} explains it in detail.
The nginx module for NixOS has native support for Let's Encrypt certificates;  {{nixos:option|services.nginx.+acme}}. The {{manual:nixos|sec=#module-security-acme-nginx|chapter=Chapter 20. SSL/TLS Certificates with ACME}} explains it in detail.


=== Minimal Example ===
=== Minimal Internet Exposed Server Example ===


Assuming that <code>myhost.org</code> resolves to the IP address of your host and port 80 and 443 has been opened.
Assuming that <code>myhost.org</code> resolves to the IP address of your host and port 80 and 443 have been opened.
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.nginx.enable = true;
services.nginx.enable = true;
Line 281: Line 281:
};
};
</syntaxhighlight>
</syntaxhighlight>
This will set up nginx to serve files for <code>myhost.org</code>, automatically request an ACME SSL Certificate and will configure systemd timers to renew the certificate if required.
This will set up nginx to serve files for <code>myhost.org</code>, automatically request an ACME SSL Certificate using a "'''HTTP-01'''" challenge (meaning your server must be exposed to the internet) and will configure systemd timers to renew the certificate if required.
 
=== Minimal Private Local LAN Server Example ===
 
We can also have a private server running in our local network (including VPN), that isn't reachable from the internet, but that still can get valid Let's Encrypt certificates that are accepted in a browser.
 
1. We have to '''modify DNS such that our domain''' like <code>myhost.org</code> '''resolves to the local IP address of our private server''' and port 80 and 443 have been opened. [https://www.youtube.com/watch?v=qlcVx-k-02E See this video tutorial] for an example on how to do that.
 
2. We have to setup the Let's Encrypt NixOS ACME services such that it uses an API token in a secrets file ([https://github.com/ryantm/agenix secrets for a server can be conveniently and securely deployed in NixOS with agenix]; just follow the tutorial) against our DNS provider to prove from our server that we own the domain. This way our server doesn't need to be exposed and reachable from the internet. NixOS ACME uses the [https://go-acme.github.io/lego/ LEGO library] to communicate to DNS providers and therefore we have to provide the token(s) in that tool's secrets format.
 
In the example we use Hetzner as our "dnsProvider" that only needs a single API token environment in our secrets file:
<syntaxhighlight lang="nix">
HETZNER_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
</syntaxhighlight>Other [https://carjorvaz.com/posts/setting-up-wildcard-lets-encrypt-certificates-on-nixos/ DNS providers need like OVH] require more environment variables.
 
See the section "Credentials" on what you have to specify in the secrets file: https://go-acme.github.io/lego/dns/hetzner/
 
See Hetzner guide on how to get an API token for its "DNS console": https://docs.hetzner.com/dns-console/dns/general/api-access-token/
 
3. Point our virtualHost to the ACME entry.
<syntaxhighlight lang="nix">
services.nginx.enable = true;
services.nginx.virtualHosts."myhost.org" = {
    addSSL = true;
    enableACME = true;
    root = "/var/www/myhost.org";
};
security.acme = {
  acceptTerms = true;
  defaults.email = "foo@bar.com";
};
</syntaxhighlight>
This will set up nginx to serve files for <code>myhost.org</code>, automatically request an ACME SSL Certificate using a "DNS-01" challenge (meaning your server must not be exposed to the internet) and will configure systemd timers to renew the certificate if required.


== Troubleshooting ==
== Troubleshooting ==