summaryrefslogtreecommitdiffstats
path: root/ACME.md
blob: 78e5ebe70807fe977aaf6238df59b0d14f282bab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
We have our own letsencrypt-like service (ca.r) for internal certificates on the retiolum network.

## Overview

The `ca.r` is a self-hosted ACME CA using step-ca that issues certificates for `.r` and `.w` domains on the retiolum network. This allows services to use proper TLS certificates without relying on public certificate authorities.

## Trust the CA (Using Retiolum Module - Recommended)

The easiest way to trust the ca.r certificates is using the retiolum CA module:

```nix
# flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    retiolum.url = "github:Mic92/retiolum";
  };

  outputs = { self, nixpkgs, retiolum }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      modules = [
        retiolum.nixosModules.ca
        {
          # This makes your system trust the Krebs CA certificates
          retiolum.ca = {
            trustIntermediate = true;  # Trust intermediate CA for .r and .w domains (default)
            trustRoot = false;         # Optionally trust root CA (default: false)
            acmeURL = "https://ca.r/acme/acme/directory";  # ACME server URL
          };
        }
      ];
    };
  };
}
```

### Manual Trust (Alternative)

```nix
security.pki.certificateFiles = [(pkgs.fetchurl {
  url = "http://ca.r/ca.crt";
  hash = "sha256-un5GmMplOmBgKMDhu7YcUJC0R6JFYhZgSeExOPkLs6A=";
})];
```

## Getting Certificates from ca.r

### Basic nginx configuration

```nix
services.nginx.virtualHosts."myservice.r" = {
  enableACME = true;
  forceSSL = true;
  locations."/" = {
    proxyPass = "http://localhost:8080";
  };
};
security.acme.certs."myservice.r".server = "https://ca.r/acme/acme/directory";

# Don't forget to open firewall ports
networking.firewall.allowedTCPPorts = [ 80 443 ];
```

### For services needing direct certificate access

```nix
security.acme.certs."myservice.r" = {
  server = "https://ca.r/acme/acme/directory";
  group = "myservice";  # Allow service to read certificate
  postRun = "systemctl restart myservice.service";  # Restart on renewal
};

services.myservice = {
  enable = true;
  tlsCert = "/var/lib/acme/myservice.r/fullchain.pem";
  tlsKey = "/var/lib/acme/myservice.r/key.pem";
};
```

## Using config.retiolum.ca.acmeURL

If you're using the retiolum module, you can reference the ACME URL directly:

```nix
security.acme.certs."myservice.r" = {
  server = config.retiolum.ca.acmeURL;
};
```

## Certificate Details

Certificates issued by ca.r:
- Valid for 90 days
- Automatically renewed when less than 30 days remain
- Issued by "Krebs Intermediate CA"
- Only work for `.r` and `.w` domains (enforced by name constraints)
- Use ECDSA P-256 keys by default

## Troubleshooting

### Account Does Not Exist Error

If you see: `acme: error: 400 :: urn:ietf:params:acme:error:accountDoesNotExist`

1. Stop the service: `sudo systemctl stop acme-myservice.r.timer acme-myservice.r.service`
2. Clean state: `sudo rm -rf /var/lib/acme/myservice.r /var/lib/acme/.lego/accounts/*/ca.r*`
3. Restart: `sudo systemctl start acme-myservice.r.service`

### Certificate Expired

If certificates show old dates after renewal:

1. Stop services: `sudo systemctl stop acme-myservice.r.timer acme-myservice.r.service`
2. Clean all state: `sudo rm -rf /var/lib/acme/myservice.r /var/lib/acme/.lego/myservice.r`
3. Restart: `sudo systemctl start acme-myservice.r.service && sudo systemctl start acme-myservice.r.timer`

### Checking Certificate Status

```bash
# List all ACME timers
systemctl list-timers "*acme*" --all

# Check for failed services
systemctl list-units --failed "*acme*"

# Verify certificate
echo | openssl s_client -connect myservice.r:443 -servername myservice.r 2>/dev/null | openssl x509 -noout -dates -issuer
```