Skip to content

Commit e2f55b2

Browse files
committed
ACME: module configuration.
1 parent 3905e22 commit e2f55b2

File tree

14 files changed

+2083
-49
lines changed

14 files changed

+2083
-49
lines changed

Cargo.lock

Lines changed: 358 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ rust-version = "1.81.0"
1010
crate-type = ["cdylib"]
1111

1212
[dependencies]
13+
http = "1.3.1"
14+
openssl = { version = "0.10.73", features = ["bindgen"] }
15+
openssl-foreign-types = { package = "foreign-types", version = "0.3" }
16+
openssl-sys = { version = "0.9.109", features = ["bindgen"] }
17+
siphasher = { version = "1.0.1", default-features = false }
18+
thiserror = { version = "2.0.12", default-features = false }
1319

1420
[dependencies.nginx-sys]
1521
git = "https://github.com/nginx/ngx-rust"

README.md

Lines changed: 162 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ certificate management ([ACME]) protocol.
1010

1111
### Requirements
1212

13-
* Regular nginx build dependencies
14-
* System-wide installation of OpenSSL 1.1.1 or later
15-
* Rust toolchain (1.81.0 or later)
13+
- Regular nginx build dependencies
14+
- System-wide installation of OpenSSL 1.1.1 or later
15+
- Rust toolchain (1.81.0 or later)
1616

1717
### Commands
1818

@@ -25,24 +25,181 @@ cd nginx-acme
2525
export NGINX_BUILD_DIR=$(realpath ../nginx/objs)
2626
cargo build --release
2727
```
28+
2829
The result will be located at `target/release/libnginx_acme.so`.
2930

3031
Another way is to use the provided config script:
32+
3133
```sh
3234
# in the nginx source directory
3335
auto/configure \
3436
--with-compat \
3537
--with-http_ssl_module \
3638
--add-[dynamic-]module=/path/to/nginx-acme
3739
```
40+
3841
The result will be located at `$NGX_OBJS/ngx_http_acme_module.so`.
3942

4043
Currently this method produces a slightly larger library, as we don't instruct
41-
the linker to perform dead code elimination.
44+
the linker to perform LTO and dead code elimination.
4245

4346
## How to Use
4447

45-
To be added later.
48+
Add the module to the nginx configuration,
49+
50+
```nginx
51+
load_module modules/ngx_http_acme_module.so;
52+
```
53+
54+
and configure with the directives described below
55+
56+
## Configuration directives
57+
58+
### `acme_issuer`
59+
60+
Syntax: `acme_issuer _name_ { ... }`\
61+
Context: `http`
62+
63+
Defines a new certificate issuer object.
64+
65+
#### `uri`
66+
67+
Syntax: `uri http_uri;`\
68+
Context: `acme_issuer`
69+
70+
The [directory URL] of the ACME server. This is the only mandatory parameter
71+
in the `acme_issuer` block.
72+
73+
[directory URL]: https://www.rfc-editor.org/rfc/rfc8555#section-7.1.1
74+
75+
#### `account_key`
76+
77+
Syntax: `account_key alg[:size]|file;`\
78+
Context: `acme_issuer`
79+
80+
The account's private key used for request authentication.
81+
Accepted values:
82+
83+
- `ecdsa:256/384/521` for `ES256`/`ES384`/`ES512` JSON Web Signature algorithms
84+
- `rsa:2048..4096` for `RS256`
85+
- File path for an existing key, using one of the algorithms above.
86+
87+
The generated account keys are preserved across reloads, but will be lost on
88+
restart unless `state_path` is configured.
89+
90+
#### `contact`
91+
92+
Syntax: `contact _url_;`\
93+
Context: `acme_issuer`
94+
95+
An array of URLs that the ACME server can use to contact the client for issues
96+
related to this account.
97+
98+
Can be specified multiple times.
99+
100+
#### `resolver`
101+
102+
Syntax: `resolver address ... [valid=time] [ipv4=on|off] [ipv6=on|off] [status_zone=zone];`\
103+
Default: `---`\
104+
Context: `acme_issuer`
105+
106+
Configures name servers used to resolve names of upstream servers into
107+
addresses.
108+
109+
Required, but can be inherited from the `http` block.
110+
111+
#### `resolver_timeout`
112+
113+
Syntax: `resolver_timeout time;`\
114+
Default: `30s`\
115+
Context: `acme_issuer`
116+
117+
Sets a timeout for name resolution.
118+
119+
#### `ssl_trusted_certificate`
120+
121+
Syntax: `ssl_trusted_certificate file;`\
122+
Default: `system CA bundle`\
123+
Context: `acme_issuer`
124+
125+
Specifies a file with trusted CA certificates in the PEM format used to verify
126+
the certificate of the ACME server.
127+
128+
#### `ssl_verify`
129+
130+
Syntax: `ssl_verify on|off;`\
131+
Default: `on`\
132+
Context: `acme_issuer`
133+
134+
Enables or disables verification of the ACME server certificate.
135+
136+
#### `state_path`
137+
138+
Syntax: `state_path _path_;`\
139+
Default: `---`\
140+
Context: `acme_issuer`
141+
142+
Defines a directory for storing the module data that can be persisted across
143+
restarts. This could greatly improve the time until the server is ready and
144+
help with rate-limiting ACME servers.
145+
146+
The directory, if configured, will contain sensitive content:
147+
the account key, the issued certificates and private keys.
148+
149+
### `acme_shared_zone`
150+
151+
Syntax: `acme_shared_zone size;`\
152+
Context: `http`\
153+
Default: `262k`
154+
155+
An optional directive that allows increasing the size of in-memory storage of
156+
the module.
157+
The shared memory zone will be used to store the issued certificates, keys and
158+
challenge data for all the configured certificate issuers.
159+
160+
### `acme_certificate`
161+
162+
Syntax: `acme_certificate issuer=_issuer_name_ [key=alg[:size]|file] [identifiers...];`\
163+
Context: `server`
164+
165+
Defines a certificate with the list of _identifiers_ requested from issuer
166+
_issuer_name_.
167+
168+
The `key` parameter sets the type of generated private key or a path to an
169+
existing file. Supported key algorithms and sizes:
170+
`ecdsa:256` (default), `ecdsa:384`, `ecdsa:521`, `rsa:2048`..`rsa:4096`.
171+
172+
Since 1.27.2, the `key` parameter supports the additional schemes implemented
173+
in the [`ssl_certificate_key`] directive: `data:`, `engine:` and more recently
174+
`store:`, with a caveat that password-protected keys are not supported.
175+
176+
[`ssl_certificate_key`]: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key
177+
178+
## Example configuration:
179+
180+
```nginx
181+
resolver 127.0.0.1;
182+
183+
acme_issuer example {
184+
uri https://acme.example.com/directory;
185+
contact mailto:[email protected];
186+
state_path /var/lib/nginx/acme-example;
187+
}
188+
189+
acme_shared_zone 1M;
190+
191+
server {
192+
server_name .example.test;
193+
194+
acme_certificate .example.test
195+
issuer=example
196+
key=ecdsa:256;
197+
198+
ssl_certificate $acme_certificate;
199+
ssl_certificate_key $acme_certificate_key;
200+
}
201+
202+
```
46203

47204
## License
48205

build.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,16 @@ fn detect_nginx_features() {
4444
if let Ok(os) = env::var("DEP_NGINX_OS") {
4545
println!("cargo::rustc-cfg=ngx_os=\"{os}\"");
4646
}
47+
48+
// Generate cfg values for version checks
49+
50+
println!("cargo::rustc-check-cfg=cfg(ngx_ssl_cache)");
51+
println!("cargo::rerun-if-env-changed=DEP_NGINX_VERSION_NUMBER");
52+
if let Ok(version) = env::var("DEP_NGINX_VERSION_NUMBER") {
53+
let version: u64 = version.parse().unwrap();
54+
55+
if version >= 1_027_002 {
56+
println!("cargo::rustc-cfg=ngx_ssl_cache");
57+
}
58+
}
4759
}

0 commit comments

Comments
 (0)