mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-28 14:07:13 +00:00
9b91f0f42e
Fold the standalone 3x-ui-docs project (Next.js 16 + Fumadocs, deployed to docs.sanaei.dev) into docs/ so the panel and its documentation share a single source of truth, the way sing-box keeps its docs in-tree. The old repo becomes redundant and can be retired. - Import the full site under docs/ (app, components, content, lib, public, scripts, config). The self-contained pnpm project sits alongside the existing engineering notes with no filename collisions. - Re-point "Edit on GitHub" links from MHSanaei/3x-ui-docs to this repo's docs/content/docs path (docs/lib/shared.ts, docs/app/.../page.tsx). - Add docs-ci.yml and docs-deploy.yml under .github/workflows/, scoped to docs/** and run with working-directory: docs, since GitHub only runs workflows from the repo-root .github/. deploy-static.yml's GitHub Pages publish (CNAME docs.sanaei.dev) carries over unchanged. Follow-up (outside this commit): attach the docs.sanaei.dev custom domain to this repository's Pages (or set the Vercel project's root directory to docs), confirm the site is live from the monorepo, then delete MHSanaei/3x-ui-docs.
182 lines
6.9 KiB
Plaintext
182 lines
6.9 KiB
Plaintext
---
|
|
title: SSL Certificates
|
|
description: Get and renew TLS certificates for the 3x-ui panel and inbounds — with the x-ui ACME menu (domain or bare IP), a Cloudflare DNS-01 wildcard, or manual Certbot.
|
|
icon: ShieldCheck
|
|
---
|
|
|
|
A TLS certificate lets you serve the **panel** over HTTPS (so your login and API
|
|
traffic are encrypted) and terminate TLS on **inbounds** (VLESS-TLS, Trojan,
|
|
Shadowsocks-TLS, and friends). There are three ways to obtain one:
|
|
|
|
- **The `x-ui` menu** — built-in [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)
|
|
client. Easiest for a single domain or a bare IP.
|
|
- **Cloudflare DNS-01** — also from the menu; needed for **wildcard** certs or
|
|
when port 80 is blocked / the server sits behind Cloudflare's proxy.
|
|
- **Manual Certbot** — if you'd rather manage `acme.sh`/Certbot yourself.
|
|
|
|
<Callout type="info">
|
|
If you put the panel behind Nginx or Caddy, let the proxy handle the
|
|
certificate instead — see [Reverse proxy](/docs/operations/reverse-proxy).
|
|
[REALITY](/docs/config/reality) inbounds need **no** certificate at all; they
|
|
borrow a real site's TLS. This page is for the panel and for classic TLS
|
|
inbounds.
|
|
</Callout>
|
|
|
|
## The `x-ui` SSL menu (Let's Encrypt)
|
|
|
|
Run `x-ui` and choose **`20` — SSL Certificate Management**. It drives
|
|
[acme.sh](https://github.com/acmesh-official/acme.sh) and offers:
|
|
|
|
| Option | What it does |
|
|
| ------------------------------ | ------------------------------------------------------------------- |
|
|
| Get SSL (Domain) | Issue a certificate for a domain via HTTP validation. |
|
|
| Get SSL for IP Address | Issue a short-lived (6-day, auto-renewing) cert for a **bare IP**. |
|
|
| Revoke | Revoke an existing certificate. |
|
|
| Force Renew | Renew now, before expiry. |
|
|
| Show Existing Domains | List certificates already on the server. |
|
|
| Set Cert paths for the panel | Point the panel's TLS at an issued cert (sets the fields for you). |
|
|
|
|
### Issue a certificate for a domain
|
|
|
|
<Steps>
|
|
|
|
<Step>
|
|
### Point the domain at the server
|
|
|
|
Create an `A` (and/or `AAAA`) record for your domain that resolves to this
|
|
server's public IP. Validation fails until DNS has propagated.
|
|
</Step>
|
|
|
|
<Step>
|
|
### Free up port 80
|
|
|
|
HTTP validation needs **port 80** reachable from the internet and not already in
|
|
use. Stop anything bound to it for the duration, and allow it through the
|
|
[firewall](/docs/reference/ports-firewall).
|
|
</Step>
|
|
|
|
<Step>
|
|
### Run the issuer
|
|
|
|
`x-ui` → `20` → **Get SSL (Domain)**, then enter the domain. acme.sh requests
|
|
the certificate and saves it under `/root/cert/<domain>/` as `fullchain.pem`
|
|
(the certificate chain) and `privkey.pem` (the private key).
|
|
</Step>
|
|
|
|
<Step>
|
|
### Wire it into the panel
|
|
|
|
Choose **Set Cert paths for the panel** to fill in `webCertFile` and
|
|
`webKeyFile` and restart the panel, or set them yourself in
|
|
[Panel Settings](/docs/config/panel#tls). The panel serves HTTPS as soon as both
|
|
are set.
|
|
</Step>
|
|
|
|
</Steps>
|
|
|
|
### Issue a certificate for a bare IP
|
|
|
|
No domain? Choose **Get SSL for IP Address** to obtain a short-lived
|
|
certificate (valid ~6 days, renewed automatically) bound to the server's IP.
|
|
Useful for reaching the panel over HTTPS before you've set up a domain.
|
|
|
|
## Cloudflare (DNS-01 wildcard)
|
|
|
|
DNS validation proves you control the domain by creating a TXT record instead of
|
|
answering on port 80 — so it works **behind Cloudflare's proxy**, on servers
|
|
where port 80 is blocked, and for **wildcard** certificates (`*.example.com`).
|
|
|
|
Your domain's DNS must be managed by Cloudflare, and you need one of:
|
|
|
|
- a **scoped API token** with the `Zone:DNS:Edit` permission (recommended), or
|
|
- your account **email + Global API Key**.
|
|
|
|
<Steps>
|
|
|
|
<Step>
|
|
### Create a scoped API token
|
|
|
|
In the Cloudflare dashboard go to **My Profile → API Tokens →
|
|
[Create Token](https://dash.cloudflare.com/profile/api-tokens)**, pick the
|
|
**Edit zone DNS** template, scope it to the zone you're issuing for, and create
|
|
it. Copy the token — it's shown only once.
|
|
</Step>
|
|
|
|
<Step>
|
|
### Run the Cloudflare issuer
|
|
|
|
`x-ui` → **`21` — Cloudflare SSL Certificate**. When asked, choose **`t`** for an
|
|
API token (the default) or **`g`** for the Global API Key, then enter your
|
|
domain (and, for the Global API Key, your account email and key). acme.sh creates
|
|
the TXT record, validates, and cleans it up.
|
|
</Step>
|
|
|
|
<Step>
|
|
### Point the panel at it
|
|
|
|
As with the domain flow, use **Set Cert paths for the panel** (menu `20`) or set
|
|
`webCertFile` / `webKeyFile` in [Panel Settings](/docs/config/panel#tls).
|
|
</Step>
|
|
|
|
</Steps>
|
|
|
|
<Callout type="info">
|
|
Prefer a scoped token over the Global API Key — it only grants DNS edits on the
|
|
zone you choose, so a leak can't touch the rest of your Cloudflare account.
|
|
</Callout>
|
|
|
|
## Manual (Certbot)
|
|
|
|
If you'd rather not use the menu, issue a certificate with Certbot's standalone
|
|
plugin (again, this needs port 80 free and the domain resolving to the server):
|
|
|
|
```bash
|
|
apt-get install certbot -y
|
|
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
|
certbot renew --dry-run
|
|
```
|
|
|
|
Certbot writes the certificate to `/etc/letsencrypt/live/yourdomain.com/`
|
|
(`fullchain.pem` and `privkey.pem`). Point the panel at those two files in
|
|
[Panel Settings](/docs/config/panel#tls), and set up renewal — `certbot renew`
|
|
runs on a systemd timer by default.
|
|
|
|
## Using the certificate
|
|
|
|
- **Panel** — set `webCertFile` (the full chain) and `webKeyFile` (the private
|
|
key) in [Panel Settings](/docs/config/panel#tls). Both must be set for the
|
|
panel to switch to HTTPS. Menu option **`11` — View Current Settings** prints
|
|
the paths currently in use.
|
|
- **Inbounds** — when you enable TLS on an inbound, reference the same
|
|
certificate and key files (or paste their contents) in the inbound's TLS
|
|
settings. See [Inbounds](/docs/config/inbounds) and
|
|
[Transports](/docs/config/transports).
|
|
|
|
<Callout type="warn">
|
|
Certificates expire (Let's Encrypt: 90 days; IP certs: ~6 days). The menu and
|
|
Certbot both renew automatically, but the panel keeps reading the **files** at
|
|
their fixed paths — so renew **in place** rather than moving the files, and the
|
|
panel picks up the new cert on its next restart. **Force Renew** (menu `20`)
|
|
triggers a renewal on demand.
|
|
</Callout>
|
|
|
|
## Next steps
|
|
|
|
<Cards>
|
|
<Card
|
|
title="Panel Settings"
|
|
href="/docs/config/panel#tls"
|
|
description="webCertFile / webKeyFile and the rest of the web-server settings."
|
|
/>
|
|
<Card
|
|
title="Reverse proxy"
|
|
href="/docs/operations/reverse-proxy"
|
|
description="Let Nginx or Caddy terminate TLS for you instead."
|
|
/>
|
|
<Card
|
|
title="REALITY"
|
|
href="/docs/config/reality"
|
|
description="Stealth TLS for inbounds — no certificate required."
|
|
/>
|
|
</Cards>
|