Skip to content

Commit dc477d9

Browse files
Merge pull request #32 from esnet/develop/docs
Documentation refactoring and update.
2 parents 17a31c1 + 3df18d1 commit dc477d9

59 files changed

Lines changed: 415 additions & 4519 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 25 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
# ACME Server as a Registration Authority
1+
# About
22

33
`acme-proxy` is a standalone ACME server built on [step-ca](https://github.com/smallstep/certificates) that operates in [registration authority (RA)](https://smallstep.com/docs/registration-authorities/) mode. It accepts certificate orders and validates certificate requests using the ACME protocol (RFC 8555), but does **NOT** sign certificates or store private keys.
44

5+
## Documentation
6+
7+
Checkout our [documentation site](https://software.es.net/acme-proxy) for detailed examples on usage, installation instructions, configuration etc.
8+
59
## How It Works
610

7-
`acme-proxy` runs as an ACME server inside your enterprise environment, acting as an intermediary between your internal infrastructure and an external certificate authority service (such as Sectigo). When a client successfully completes an ACME challenge, `acme-proxy` forwards the certificate signing request to an external certificate authority (CA) that supports External Account Binding (EAB). The external CA signs the certificate and returns it to the client through `acme-proxy`.
11+
`acme-proxy` runs as an ACME server inside your trusted network, acting as an intermediary between your internal infrastructure and an external certificate authority service (such as Sectigo). When a client successfully completes an ACME challenge, `acme-proxy` forwards the certificate signing request to an external certificate authority (CA) that supports External Account Binding (EAB). The external CA signs the certificate and returns it to the client through `acme-proxy`.
812

913
**Certificate Request Flow:**
1014

@@ -31,25 +35,11 @@ This architecture addresses typical enterprise constraints that prevent direct c
3135
- Legacy DNS infrastructure lacks REST API support or ACME client integration
3236
- Security policies restrict distribution of API tokens or TSIG keys for large DNS zones
3337

34-
For more information on DNS-01 security considerations:
38+
For more information on security considerations when using DNS-01 challenge:
3539

3640
- [EFF: Technical Deep Dive on ACME DNS Challenge Validation](https://www.eff.org/deeplinks/2018/02/technical-deep-dive-securing-automation-acme-dns-challenge-validation)
3741
- [LetsEncrypt: DNS-01 Challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)
3842

39-
## Benefits
40-
41-
Using ACME with commercial CAs in enterprise environments provides several advantages:
42-
43-
**Trusted Certificates:**
44-
45-
- Certificates are signed by publicly trusted CAs are already in system trust stores
46-
- Eliminates the operational burden of distributing and maintaining custom root certificates across endpoints, servers, and client devices
47-
48-
**Automation and Self-Service:**
49-
50-
- Leverage standard ACME clients (Certbot, acme.sh, cert-manager.io) for certificate issuance, automatic renewals.
51-
- Enable self-service certificate requests for development teams
52-
5343
## Quick Start
5444

5545
```sh
@@ -83,17 +73,6 @@ Requirements: Go >= 1.25
8373
cd acme-proxy && make
8474
```
8575

86-
### Using Docker
87-
88-
You can either use our [pre-built container images](https://github.com/esnet/acme-proxy/pkgs/container/acme-proxy) or you can build the image yourself.
89-
90-
**DIY - Build docker image**
91-
92-
```sh
93-
❯ git clone https://github.com/esnet/acme-proxy.git
94-
cd acme-proxy && docker build -t acme-proxy:latest .
95-
```
96-
9776
## Usage
9877

9978
Review and update configuration options in [ca.json](./ca.json) before starting the acme-proxy server.
@@ -102,7 +81,7 @@ Review and update configuration options in [ca.json](./ca.json) before starting
10281
vim ca.json
10382
```
10483

105-
The most important parts of the config are -
84+
Checkout our [official docs](https://software.es.net/acme-proxy/install/#configuration) for full set of configuration options. For quick start the most relevant config bits are:
10685

10786
```json
10887
"dnsNames": ["acmeproxy.example.com"],
@@ -117,7 +96,7 @@ The most important parts of the config are -
11796
"metrics": {
11897
"enabled": true,
11998
"port": 9234,
120-
"dataSource": "db/metrics"
99+
"dataSource": "/opt/acme-proxy/db/metrics"
121100
}
122101
},
123102
...
@@ -166,41 +145,6 @@ badger 2025/07/15 22:12:24 INFO: Replay took: 5.99µs
166145
2025/07/15 22:12:33 Serving HTTPS on proxy.example.com:443 ...
167146
```
168147

169-
When using acme-proxy with docker take a note of the bind mount and port
170-
171-
```sh
172-
$ docker run -itd -p 443:443 -v ./ca-dev.json:/acme-proxy/config/ca.json --name acme-proxy acme-proxy:latest
173-
29c1ca374832dc50d3215b404f620c2a08d988c30f630464bf9d7d35aa44345f
174-
175-
$ docker logs acme-proxy
176-
2026/03/17 23:04:06 Building new tls configuration using step-ca x509 Signer Interface
177-
2026/03/17 23:04:07 [INFO] acme: Registering account for certadmin@example.com
178-
2026/03/17 23:04:07 INFO processing certificate request domains=[proxy.example.com]
179-
2026/03/17 23:04:07 [INFO] [proxy.example.com] acme: Obtaining bundled SAN certificate given a CSR
180-
2026/03/17 23:04:08 [INFO] [proxy.example.com] AuthURL: https://acme.sectigo.com/v2/InCommonRSAOV/authz/jQJHRdd-0kKdm-JVQVhjHQ
181-
2026/03/17 23:04:08 [INFO] [proxy.example.com] acme: authorization already valid; skipping challenge
182-
2026/03/17 23:04:08 [INFO] [proxy.example.com] acme: Validations succeeded; requesting certificates
183-
2026/03/17 23:04:08 [INFO] Wait for certificate [timeout: 30s, interval: 500ms]
184-
2026/03/17 23:04:13 [INFO] [proxy.example.com] Server responded with a certificate.
185-
2026/03/17 23:04:13 INFO obtained certificate from external CA domains=[proxy.example.com]
186-
2026/03/17 23:04:13 Starting Smallstep CA/0000000-dev (linux/amd64)
187-
2026/03/17 23:04:13 Documentation: https://u.step.sm/docs/ca
188-
2026/03/17 23:04:13 Community Discord: https://u.step.sm/discord
189-
2026/03/17 23:04:13 Config file: /acme-proxy/config/ca.json
190-
2026/03/17 23:04:13 The primary server URL is https://proxy.example.com:443
191-
2026/03/17 23:04:13 Root certificates are available at https://proxy.example.com:443/roots.pem
192-
2026/03/17 23:04:13 Serving HTTPS on :443 ...
193-
194-
$ curl -s https://proxy.example.com/acme/acme/directory | jq .
195-
{
196-
"newNonce": "https://proxy.example.com/acme/acme/new-nonce",
197-
"newAccount": "https://proxy.example.com/acme/acme/new-account",
198-
"newOrder": "https://proxy.example.com/acme/acme/new-order",
199-
"revokeCert": "https://proxy.example.com/acme/acme/revoke-cert",
200-
"keyChange": "https://proxy.example.com/acme/acme/key-change"
201-
}
202-
```
203-
204148
### Obtaining a certificate
205149

206150
While the example below uses `acme.sh` as the ACME client, we've also tested using `certbot` with equal success.
@@ -283,11 +227,11 @@ Certificate:
283227
284228
```
285229

286-
We have our certificate signed by InCommon 🎉
230+
We have our certificate signed by our certificate authority i.e InCommon 🎉
287231

288232
### Renewing a certificate
289233

290-
Issuing a certificate is *generally* not a problem in enterprise environments. But the ability to reliably renew certificates and reload services gracefully post renewal is. I am using the `--force` flag for renewal only because the default configuration in ACME clients only performs automatic renewal `1 < N < 30` number of days before certificate expiration.
234+
Issuing a certificate is *generally* not a problem in enterprise environments. But the ability to automatically renew certificates and reload services gracefully post renewal is. I am using the `--force` flag for renewal only because the default configuration in ACME clients only performs automatic renewal `1 < N < 30` number of days before certificate expiration.
291235

292236
```sh
293237
$ ./acme.sh --renew --domain myserver.example.com --force
@@ -342,3 +286,17 @@ N+c9XyDLAiEAkbrRKBsYc8YSgYviREF9u+gz7jK5JY2dsaRatEfb8Eg=
342286
```
343287

344288
Cert renewal was a success!
289+
290+
## Benefits
291+
292+
Using ACME with commercial CAs in enterprise environments provides several advantages:
293+
294+
**Trusted Certificates:**
295+
296+
- Certificates are signed by publicly trusted CAs are already in system trust stores
297+
- Eliminates the operational burden of distributing and maintaining custom root certificates across endpoints, servers, and client devices
298+
299+
**Automation and Self-Service:**
300+
301+
- Leverage standard ACME clients (Certbot, acme.sh, cert-manager.io) for certificate issuance, automatic renewals.
302+
- Enable self-service certificate requests for development teams

develop/contribute.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
+++
2-
title = 'Contributing'
3-
weight = 50
4-
+++
5-
61
# Setup development environment
72

83
1. Install `go >= 1.25`
@@ -14,5 +9,5 @@ weight = 50
149

1510
1. Fork the repo
1611
2. In your fork, create a new branch for your work
17-
3. Commit & push changes to your fork
12+
3. Add changes in your branch, Commit & push changes to your forked repo
1813
4. Submit a pull request

develop/externalcas.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
+++
2-
title = 'External CAs'
3-
weight = 30
4-
BookToC = true
5-
+++
6-
71
# ACME server as Registration Authority
82

93
See [upstream docs](#upstream-docs) section for more background on what registration authority, CAS are and how those concepts fits into step-ca architecture.

develop/maintenance.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
+++
2-
title = 'Maintenance'
3-
weight = 40
4-
BookToC = true
5-
+++
6-
71
# Guide to patching upstream related changes
82

93
- While smallstep/certifiates is meant to serve as the upstream Go module for acme-proxy, we have to maintain some patches/fixes ourselves until they get merged upstream. Our patched version of step-ca is currently maintained in a forked repo [esnet/certificates](https://github.com/esnet/certificates).

docs/config/_default/hugo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
baseURL = 'http://docs.acme-proxy.es.net'
2-
title = 'ACME Proxy'
1+
baseURL = 'http://docs.acme-proxy.es.net/'
2+
title = 'acme-proxy'
33
theme = 'hugo-book'
44

55
# Book configuration

docs/content/_index.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
+++
2-
title = 'ACME Proxy'
2+
title = 'acme-proxy'
33
+++
44

5-
# What is ACME Proxy?
5+
## What is acme-proxy?
66

7-
`acme-proxy` is a standalone ACME server built on [step-ca](https://github.com/smallstep/certificates) that operates in [registration authority (RA)](https://smallstep.com/docs/registration-authorities/) mode. It runs as a standalone server inside your enterprise environment, acting as an intermediary between your internal infrastructure and an external certificate authority service (such as Sectigo). It accepts certificate orders and validates certificate requests using the ACME protocol (RFC 8555), but does **NOT** sign certificates or store private keys.
7+
`acme-proxy` is a standalone ACME server built on [step-ca](https://github.com/smallstep/certificates) that operates in [registration authority (RA)](https://smallstep.com/docs/registration-authorities/) mode. It runs as a standalone server inside your enterprise environment, acting as an intermediary between your internal infrastructure and an external certificate authority service (such as Sectigo, DigiCert or ZeroSSL). It accepts certificate orders and validates certificate requests using the ACME protocol (RFC 8555), but does **NOT** sign certificates or store private keys.
88

99
{{< image src="/assets/highlevel-flow.png" alt="sequence" >}}
1010

11-
# Certificate Request Flow
11+
## Certificate issuance flow
1212

1313
1. Your internal server (behind a firewall perimeter) requests a certificate from `acme-proxy` using standard ACME clients like certbot, acme.sh or cert-manager.io if you're using Kubernetes.
1414
2. `acme-proxy` presents cryptographic challenges to verify domain ownership
@@ -17,3 +17,29 @@ title = 'ACME Proxy'
1717
5. `acme-proxy` retrieves the certificate bundle and returns it to your server
1818

1919
{{< image src="/assets/sequence.png" alt="sequence" >}}
20+
21+
## Connectivity Requirements
22+
23+
For the ACME certificate request issuance, renewal flow to work correctly, make sure your any internal firewalls, ACLs, IPtables rules permit the following traffic.
24+
25+
**Client to acme-proxy (HTTPS/443)**
26+
27+
Your servers running certbot must be able to connect to acme-proxy over HTTPS.
28+
29+
```
30+
Source myserver.example.com
31+
Destination acme-proxy.example.com
32+
Protocol https (443)
33+
Action allow
34+
```
35+
36+
**acme-proxy to Client (HTTP/80)**
37+
38+
`acme-proxy` validates HTTP-01 challenges by connecting to your servers directly on port 80. Your servers must allow inbound HTTP/80 from acme-proxy's IP — not from the public internet. This is the key security benefit: HTTP/80 exposure is limited to a trusted internal host rather than the global internet which is the case when using LetsEncrypt.
39+
40+
```
41+
Source acme-proxy.example.com
42+
Destination myserver.example.com
43+
Protocol http (80)
44+
Action allow
45+
```

docs/content/client.md

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ For certificate issuance commands and per-scenario usage, see [user.md](./user.m
2323

2424
## Installing ACME Clients
2525

26-
### Certbot
27-
26+
{{< tabs >}}
27+
{{% tab "Certbot" %}}
2828
> **Note:** Certbot's actively maintained distribution is via Snap. The `.deb` packages available in apt repositories are no longer maintained by the Certbot project and ship outdated versions.
2929
3030
Install via Snap:
@@ -49,11 +49,9 @@ For the Apache plugin:
4949
sudo snap set certbot trust-plugin-with-root=ok
5050
sudo snap install certbot-apache
5151
```
52+
{{% /tab %}}
5253

53-
---
54-
55-
### acme.sh
56-
54+
{{% tab "acme.sh" %}}
5755
**Debian / Ubuntu:**
5856

5957
```bash
@@ -71,11 +69,9 @@ sudo dnf install -y acme.sh socat
7169
The package installs the binary to `/usr/bin/acme.sh`. Use `/etc/acme.sh` as the configuration home for system-wide installations (passed via `--home` in all commands).
7270

7371
> **`socat` is required for standalone mode.** acme.sh uses `socat` to bind port 80 for HTTP-01 challenges in standalone mode. It is installed above alongside acme.sh. This is not required if you use NGINX or Apache plugin mode.
72+
{{% /tab %}}
7473

75-
---
76-
77-
### Lego
78-
74+
{{% tab "Lego" %}}
7975
Lego has no official packages in major Linux distribution repositories. Install the release binary directly:
8076

8177
```bash
@@ -88,29 +84,33 @@ lego --version
8884
```
8985

9086
> Verify the checksum from the [GitHub releases page](https://github.com/go-acme/lego/releases) before deploying to production. Pin `LEGO_VERSION` in your configuration management tool and treat upgrades as a deliberate change.
87+
{{% /tab %}}
88+
{{< /tabs >}}
9189

9290
---
9391

9492
## Account Registration
9593

9694
Each ACME client must register an account with acme-proxy before any certificates can be issued. This is a one-time step per host.
9795

98-
### Certbot
99-
96+
{{< tabs >}}
97+
{{% tab "Certbot" %}}
10098
Certbot registers automatically on first use. No separate registration step is required.
99+
{{% /tab %}}
101100

102-
### acme.sh
103-
101+
{{% tab "acme.sh" %}}
104102
```bash
105103
sudo acme.sh --register-account \
106104
--server https://acme-proxy.example.com/acme/acme/directory \
107105
--email admin@example.com \
108106
--home /etc/acme.sh
109107
```
108+
{{% /tab %}}
110109

111-
### Lego
112-
110+
{{% tab "Lego" %}}
113111
Lego registers automatically on the first `run` invocation. No separate registration step is required.
112+
{{% /tab %}}
113+
{{< /tabs >}}
114114

115115
---
116116

@@ -124,10 +124,8 @@ Replacing cron-based renewal with systemd timers provides:
124124

125125
All service units below set `SyslogIdentifier` so logs can be filtered by tag regardless of which syslog daemon is in use.
126126

127-
---
128-
129-
### Certbot
130-
127+
{{< tabs >}}
128+
{{% tab "Certbot" %}}
131129
The Snap-installed certbot ships `certbot.timer` and `certbot.service` units automatically. Enable the timer and confirm it is active:
132130

133131
```bash
@@ -153,11 +151,9 @@ sudo systemctl daemon-reload
153151
```bash
154152
sudo certbot renew --dry-run
155153
```
154+
{{% /tab %}}
156155

157-
---
158-
159-
### acme.sh
160-
156+
{{% tab "acme.sh" %}}
161157
acme.sh's `--cron` flag iterates over all configured certificates and renews those expiring within 30 days. A single service and timer unit covers all certificates on the host.
162158

163159
**Create the service unit:**
@@ -209,11 +205,9 @@ sudo systemctl enable --now acme-renewal.timer
209205
systemctl status acme-renewal.timer
210206
systemctl list-timers acme-renewal.timer
211207
```
208+
{{% /tab %}}
212209

213-
---
214-
215-
### Lego
216-
210+
{{% tab "Lego" %}}
217211
Lego has no built-in renewal scheduling. Create service and timer units manually.
218212

219213
Unlike acme.sh and certbot, lego's `renew` command targets one domain at a time. If you manage multiple certificates, use a wrapper script.
@@ -297,6 +291,8 @@ sudo systemctl enable --now lego-renewal.timer
297291
systemctl status lego-renewal.timer
298292
systemctl list-timers lego-renewal.timer
299293
```
294+
{{% /tab %}}
295+
{{< /tabs >}}
300296

301297
---
302298

docs/content/firewall.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)