anycert is a cross-platform certificate toolkit for private networks, homelabs, and enterprise self-hosted deployments.
It creates your own local CA, issues trusted HTTPS certificates for localhost and internal hosts, and helps you deploy them across Proxmox VE, OpenMediaVault, Unraid, Docker, Nginx, and Node.js services — fully offline, with no public domain required.
English | 繁體中文 | 🌐 Official Website (GitHub Pages)
Server (generate & deploy certs + Nginx landing page):
git clone https://github.com/anomixer/anycert.git
cd anycert
sudo bash anycert.sh # Windows Server: run anycert.bat as AdministratorEach Client (trust the CA — Option A Recommended):
- Option A (Recommended ⭐ Web Browser Setup): Open
http://<SERVER_IP>/in your browser, click the download button on the AnyCert Landing Page to download & run the installer script for your OS! - Option B (CLI):
# Windows: right-click anycert-windows.bat → Run as Administrator # Linux: sudo bash anycert-linux.sh # macOS: sudo bash anycert-macos.sh
Done. Access your server securely via https://<your-fqdn>:<port> or https://<your-ip>:<port>.
How does anycert compare with other internal TLS/HTTPS solutions?
| Feature | Ad-hoc Self-Signed (e.g. app-default) | Let's Encrypt (DNS-01 / Cloudflare) | Tunnels (Cloudflared / ngrok) | Mesh VPN (Tailscale HTTPS) | anycert (This Script) |
|---|---|---|---|---|---|
| Browser Lock 🔒 | ❌ No (Shows red warning / Not Secure) | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes (After client setup) |
| Needs Public Domain | ✅ No | ❌ Yes | ❌ Yes | ✅ No | ✅ No |
| Needs Internet | ✅ No | ❌ Yes | ❌ Must be online | ❌ Must be online | ✅ No — Works 100% offline |
| Exposes Hostname | ✅ No | ❌ Yes (CT logs) | ❌ Yes (CT logs) | ✅ No | ✅ No |
| Isolated LAN Support | ✅ Yes | ❌ No | ❌ No | ❌ No | ✅ Yes |
| No Client Reconfig on Renew | ❌ No (Must re-accept warnings / re-import certs on all clients) | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes (Root CA stays trusted) |
| LAN Data Stays Local | ✅ Yes | ✅ Yes | ❌ No (Routes via external edge nodes) | ❌ No (Often routes via DERP relays) | ✅ Yes — Full LAN speeds |
| Client Maintenance & Setup | ❌ High (Manual exceptions / imports on every client for every renewal) | ✅ None (Browsers natively trust public CA) | ✅ None (Browsers natively trust public CA) | ❌ Medium (Requires installing & running client agent on all devices) | ✅ Low (One-time client script run, no background daemon/agent) |
| Cost | Free | Free (Must renew every 3 months) | Free / Paid plans | Free / Paid plans | Free |
| FQDN Access | ✅ Yes | ✅ Yes | ✅ Yes (Limited to *.ts.net) |
✅ Yes | |
| IP Access | ❌ No | ❌ No | ❌ No | ✅ Yes (SAN contains multiple IPs) | |
| Complexity | None | High | Medium | Medium | Low (One command server, one command client) |
- Let's Encrypt + Cloudflare: Best for homelabs with public domains where you don't mind exposing hostnames to public Certificate Transparency logs.
- Cloudflared / ngrok: Good for exposing internal services to the public internet, but poses security risks and fails in offline/LAN environments.
- Tailscale HTTPS: Great if your entire fleet is already on Tailscale, but requires an active internet connection to update certificates and forces you to use
*.ts.netdomains. - anycert: Ideal for fully offline, air-gapped, or secure internal LANs where no public exposure is wanted, data privacy is critical, and direct IP access is preferred. It supports adding multiple IP addresses (e.g. physical LAN + Tailscale/VPN virtual IPs) to the certificate's SAN, making it fully trustable across multiple networks.
mkcert is a popular zero-config tool for generating locally-trusted development certificates. anycert covers the same use case and more. Here's how the two compare:
| Feature | mkcert | anycert Profile [4] Generate Only | anycert Profile [3] Custom Path | anycert Profile [1] Nginx SSL Proxy |
|---|---|---|---|---|
| Local Dev HTTPS (localhost) | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| LAN / IP SAN support | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Installs CA to system trust store | ✅ Auto | ✅ Auto (via client script) | ✅ Auto (via client script) | ✅ Auto (server-side) |
| Installs CA to Firefox / Chrome NSS | ✅ Yes | ✅ Yes (via client script) | ✅ Yes (via client script) | ✅ Yes (via client script) |
| Copies cert to service path | ❌ Manual | ❌ Manual | ✅ Auto | ✅ Auto (Nginx) |
| Auto service reload after deploy | ❌ No | ❌ No | ✅ Configurable | ✅ Yes (Nginx reload) |
| Auto-installs reverse proxy (Nginx) | ❌ No | ❌ No | ❌ No | ✅ Yes |
| LAN multi-device CA distribution | ❌ Manual (copy rootCA.pem yourself) | ✅ Client script auto-fetches & imports | ✅ Client script auto-fetches & imports | ✅ Client script auto-fetches & imports |
| Hosts file update on clients | ❌ Manual | ✅ Auto (client script) | ✅ Auto (client script) | ✅ Auto (client script) |
| Binary install required | ✅ No (pure shell/bat) | ✅ No (pure shell/bat) | ✅ No (pure shell/bat) | |
| Windows support | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| macOS support | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Linux support | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
In short: anycert Profile [4] Generate Only is the closest equivalent to mkcert — both just generate a trusted cert and let you configure the service yourself. Profile [3] Custom Path goes one step further by auto-copying certs to your service directory and reloading it. Profile [1] Nginx SSL Proxy is the full-stack option that mkcert doesn't offer at all — it wraps your plain HTTP services in HTTPS automatically, with no changes to your existing apps.
If you're already happy with mkcert for simple local dev on a single machine, great. Choose anycert when you need LAN-wide trust distribution, multi-device client setup automation, or automatic proxy wrapping without touching your existing services.
Why is the Root CA valid for 10 years (3650 days), while the server cert is only 825 days? Modern operating systems and browsers (like Apple iOS/macOS Safari and Google Chrome) enforce a strict security policy: any leaf SSL/TLS server certificate signed by a private CA must have a maximum validity of 825 days (approx. 2.2 years). If it exceeds 825 days, the browser will block the connection with an invalid certificate warning.
To bypass this restriction while providing a seamless user experience, anycert uses a dual-layer setup:
- Root CA (10 years): Installed and trusted on the client device. It remains unchanged.
- Server Certificate (825 days): Installed on the server.
Since the Root CA trusted by your clients remains unchanged, when the server certificate expires, you only run the script on the server to regenerate it. The clients will automatically trust it without any re-importing or reconfiguration. This achieves the "configure once, trusted forever" convenience.
In team environments or local development (specifically when using Service Profile [1] - Nginx SSL Proxy), a common question is: "Why not map services to subdomains like https://app1.demo.local on port 443, instead of using a single FQDN with different ports (e.g., :13000, :16502)?"
This is a deliberate design choice to eliminate the "Hosts Modification Hell" problem:
| Feature | Option A: Subdomain Routing (Port 443) | Option B: Anycert's Port Offsetting (Shared FQDN) |
|---|---|---|
| URL Look | Clean (e.g., https://llmchat.demo.local) |
Contains port (e.g., https://server.demo.local:13000) |
| Adding a Service | ❌ Every developer/client machine must modify their hosts file. Each new web service requires updating /etc/hosts on all client PCs, or DNS resolution will fail. If you have a self-hosted DNS (e.g., Pi-hole, Unbound) or router with built-in DNS capabilities, you can configure subdomain resolution on the DNS server/router, but this requires admin privileges. |
⚡ Clients never have to update again! Because all services share the same FQDN, clients set up hosts once on Day 1, and can immediately connect to any new service on different ports. |
| Cert Management | ❌ Requires issuing certificates for each subdomain, or managing complex self-signed Wildcard certs. | 🛡️ Single certificate containing IP SANs. Nginx reloads automatically. Setup overhead is zero. |
Conclusion: The biggest pain point in self-hosted development environments isn't remembering port numbers — it's updating hosts files on client machines. Anycert's Port Offsetting design is the most practical, zero-maintenance solution.
Using HTTPS on a local area network (LAN) provides critical benefits beyond simply eliminating browser warning screens:
Modern browsers (like Chrome, Safari, Edge) enforce a strict security policy that disables many powerful web APIs unless the page is loaded in a "Secure Context" (i.e., over https:// or on http://localhost only when accessed locally on the server machine).
If you connect from other devices on the LAN (like your phone, tablet, or another laptop) using plain http:// with a local IP or custom FQDN, the browser will flag the connection as insecure and forcefully disable:
- Clipboard Operations (Clipboard API): This is a major pain point! In local LLM chat applications (e.g., Open WebUI, LLMChat), clicking the "Copy Code" button on code blocks will completely fail under HTTP cross-device connections.
- Microphone & Camera Access: Speech-to-Text inputs and AI voice chat features cannot access your microphone if the URL is not HTTPS.
- PWA Installation (Progressive Web Apps): You cannot install local web apps to your desktop or mobile home screen, nor can you use offline features (Service Workers).
- Hardware Integration: Gamepad API (game controllers), WebBluetooth, WebUSB, and MIDI keyboard integrations will be disabled.
- Credential APIs & Passwordless Login (Web Crypto / Passkeys): Generating or registering passkeys requires HTTPS.
In shared network environments (such as offices, schools, co-living spaces, or public Wi-Fi), unencrypted HTTP traffic can be easily sniffed by anyone on the same network using tools like Wireshark. HTTPS encrypts all communication, preventing:
- Theft of login credentials to your self-hosted services.
- Sniffing of sensitive AI API Keys (such as OpenAI/Anthropic tokens) transmitted to local LLMs.
- Local eavesdropping on private LLM chats and database payloads.
Modern browsers (such as Google Chrome) enforce a strict "Insecure Downloads" policy. If a page is loaded via an insecure connection (plain HTTP), trying to download files (like backups, application logs, AI model weights, or exported files) will trigger a warning. The browser will flag it as an insecure download, block it, and force the user to manually expand settings and select "Keep anyway" to obtain the file. Serving your local tools over HTTPS solves this, allowing downloads to complete smoothly.
anycert is fully cross-platform and has been thoroughly tested under real-world LAN environments. The testing matrix below showcases the compatibility of both server setup and client trust automation:
| Server OS / Platform | Windows | Linux | macOS | WSL 2 | Proxmox VE |
|---|---|---|---|---|---|
| Server Script | anycert.bat |
anycert.sh |
anycert.sh |
anycert.sh |
anycert.sh |
| Server Installation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Local Browser Access on Server | ✅ | ✅ | ✅ | ✅ | N/A (No GUI) |
| Need local client setup? | ✅ No | ✅ Yes | ✅ Yes | ✅ Yes | N/A (No GUI) |
| Client OS \ Server Platform | Windows | Linux | macOS | WSL 2 | Proxmox VE |
|---|---|---|---|---|---|
anycert-windows.bat (Windows Client) |
✅ | ✅ | ✅ | ✅ | ✅ |
anycert-linux.sh (Linux Client) |
✅ | ✅ | ✅ | ✅ | ✅ |
anycert-macos.sh (macOS Client) |
✅ | ✅ | ✅ | ✅ | ✅ |
| File | Platform | Usage |
|---|---|---|
anycert.sh |
Linux (including WSL) / macOS Server | Generates Root CA + Server cert, supports PVE, Nginx SSL Proxy (Recommended), Custom Paths, and reload commands |
anycert.bat |
Windows Server | Generates Root CA + Server cert, supports Nginx SSL Proxy (Recommended), Custom Paths, and reload commands |
| File | Platform | Usage |
|---|---|---|
anycert-windows.bat |
Windows Client | Downloads CA cert, updates hosts, imports to Windows Trust Store |
anycert-linux.sh |
Linux Client (Ubuntu/Debian) | Downloads CA cert, updates hosts, imports to system and browser (Chrome/Firefox) Trust Stores |
anycert-macos.sh |
macOS Client | Downloads CA cert, updates hosts, imports to macOS Keychain |
Clone this repo and run anycert.sh:
git clone https://github.com/anomixer/anycert.git
cd anycert
sudo bash anycert.shThe script will:
- Auto-detect your IP, hostname, and FQDN. You can confirm them and optionally input additional space-separated IP addresses (e.g. Tailscale IP, VPN IP, or other LAN IPs) to be included in the certificate's SAN (Subject Alternative Name) and Nginx's
server_namerules. - Let you choose a deployment profile (offers 4 options on standard servers, and auto-detects Proxmox VE to offer 5 options):
- [1] Auto-Setup Nginx SSL Proxy [Single-Host] [Lazy-Friendly / Recommended]: Scans listening TCP ports, lets you pick which ones to expose, automatically installs Nginx, and wraps local HTTP ports into HTTPS (
Port + offsettoHTTP Port). The offset defaults to 10000 (e.g.3000 -> 13000). - [2] Auto-Setup Nginx SSL Gateway [Dedicated Gateway / Multi-Host]: Specifically for dedicated Gateway VMs/hosts. Bypasses local port scans, prompts for backend
IP:PORTmappings, and defaults to no port offset (1-to-1 mapping, e.g., HTTPS3000proxies to backend3000directly). - [3] Custom Path: Installs certs to custom target paths and runs a custom service reload command (for services that already support native HTTPS).
- [4] Generate Only: Just generates the certificates in
/etc/anycert/for manual setup. - [5] Proxmox VE (PVE): (Only displayed on PVE systems) Automatically backs up and replaces the default PVE certs, then restarts
pveproxy.
- [1] Auto-Setup Nginx SSL Proxy [Single-Host] [Lazy-Friendly / Recommended]: Scans listening TCP ports, lets you pick which ones to expose, automatically installs Nginx, and wraps local HTTP ports into HTTPS (
💡 Tip (Local Browser Access on Server) If you want the browser running on this server itself (e.g. to access local HTTPS wrappers on the server machine) to trust the CA, you do not need to look for server-side imports. You can simply run the client script (
anycert-macos.shoranycert-linux.sh) locally on this server. Specify127.0.0.1as the Server IP and select the local CA import option, and it will configure your hosts, Keychain, and Chrome/Firefox NSS databases automatically!
Workflow by profile:
Profile [1] Nginx SSL Proxy — Best for plain HTTP services or multi-container setups. Apps keep their HTTP port; HTTPS is served on Port + offset (defaults to 10000, customizable):
flowchart LR
subgraph nginxProxy [Nginx SSL Proxy]
ClientHTTP["Client http://ip:3000"] --> AppHTTP["App still on HTTP:3000"]
ClientHTTPS["Client https://ip:13000"] --> NginxSSL["Nginx SSL:13000"]
NginxSSL --> AppHTTP
end
Profile [2] Nginx SSL Gateway — Best for setting up this machine as a dedicated Gateway VM/LXC running only Nginx, which decrypts HTTPS traffic and forwards it to other servers with different IPs in the LAN. By default, there is no port offset (1-to-1 mapping, e.g., Nginx listens on HTTPS 3000 and proxies to backend 3000 directly):
flowchart TD
subgraph LAN ["Local Network Area"]
Client["Client Laptop\nTrusts CA & Binds Hosts\n(gateway.demo.local -> Host C)"]
subgraph HostC ["Host C: SSL Gateway 172.16.1.3"]
Nginx["Nginx SSL Proxy\n(anycert Certificate)"]
end
subgraph HostA ["Host A: PVE 172.16.1.1"]
PVE["PVE Web (HTTP:8006)"]
end
subgraph HostB ["Host B: App Server 172.16.1.2"]
OpenWebUI["Open WebUI (HTTP:3000)"]
Ollama["Ollama API (HTTP:11434)"]
end
Client -- "https://gateway.demo.local:3000 (HTTPS)" --> Nginx
Client -- "https://gateway.demo.local:8006 (HTTPS)" --> Nginx
Nginx -- "proxy_pass http://172.16.1.1:8006" --> PVE
Nginx -- "proxy_pass http://172.16.1.2:3000" --> OpenWebUI
Nginx -- "proxy_pass http://172.16.1.2:11434" --> Ollama
end
💡 Multi-Host Deployment Example: Suppose you have 3 hosts in your local network:
- Host A (IP:
172.16.1.1): Running PVE (8006)- Host B (IP:
172.16.1.2): Running Ollama (11434) and Open WebUI (3000)- Host C (IP:
172.16.1.3): A clean VM/host dedicated for Nginx SSL GatewayDeployment Steps:
- Server Setup: Only run
anycert.shon Host C once.
- Choose Option
[2] Auto-Setup Nginx SSL Gateway [Dedicated Gateway / Multi-Host].- Enter the backend list:
172.16.1.1:8006 172.16.1.2:11434 172.16.1.2:3000.- Keep the port offset at
0(1-to-1 forwarding).- Nginx on Host C will now automatically listen on HTTPS ports
3000,8006, and11434and encrypt-forward them to their backends.- Client Setup: Run the client setup script on your work laptop, and specify Host C's IP
172.16.1.3as the Server IP.- Result: Your laptop can now securely access Open WebUI via
https://gateway.demo.local:3000and PVE viahttps://gateway.demo.local:8006without warnings. Only Host C needs to manage the SSL certificate!
Profile [3] Custom Path — Best when the service already terminates HTTPS (OMV, IIS, your own Nginx, etc.). Certs are copied in-place; clients use the native port:
flowchart LR
subgraph customPath [Custom Path]
AnyCert["anycert copies cert + key"] --> ServiceCert["Service cert path"]
ClientHTTPS["Client https://ip:nativePort"] --> ServiceTLS["Service terminates TLS"]
ServiceCert --> ServiceTLS
ServiceTLS --> AppBackend["App / Web UI"]
end
Profile [4] Generate Only — Issues and saves cert files only; you configure each service manually afterward:
flowchart LR
subgraph generateOnly [Generate Only]
AnyCertGen["anycert issues certs"] --> CertDir["Saved in anycert dir only"]
CertDir --> UserManual["User copies and configures"]
UserManual --> EachService["Per-service HTTPS setup"]
end
Profile [5] Proxmox VE (Linux PVE only) — Automated Custom Path; replaces pveproxy certs directly:
flowchart LR
subgraph pveMode [Proxmox VE]
AnyCertPVE["anycert replaces PVE certs"] --> PVEProxy["pveproxy"]
ClientHTTPS["Client https://ip:8006"] --> PVEProxy
end
Run Command Prompt (cmd) as Administrator and execute:
anycert.batThe script will search for OpenSSL (e.g. from Git for Windows), generate the certificates, and allow you to deploy them using the Nginx automatic proxy (automatic download & setup) or to custom paths (e.g. IIS).
Note
Windows Nginx Deployment
If you choose Nginx SSL Proxy and Nginx is not found locally, the script will automatically download Nginx from the official website and extract it to C:\nginx\ using Windows native curl.exe and tar.exe. In isolated or offline network environments, you can manually download the Nginx zip and extract it to C:\nginx ensuring C:\nginx\nginx.exe exists.
Tip
✨ Smart Configuration & Update Menu
If your server already has anycert certificates installed, executing anycert.sh or anycert.bat again will automatically detect the installation and present an action menu:
- Update/Modify Nginx Ports: Change proxy port mappings without regenerating certificates.
- Overwrite Mode: Enter a space-separated list of ports (e.g.
3000 8080) to completely overwrite the current ports. - Adjustment Mode: Prefix ports with
+or-(e.g.+8080 -3000) to incrementally add8080and remove3000from Nginx proxy wrappers. Nginx configuration will reload automatically.
- Overwrite Mode: Enter a space-separated list of ports (e.g.
- Renew/Regenerate SSL Certificates: Keeps the existing Nginx proxy ports configuration but renews expired server certificates.
- Uninstall: Completely restores the original settings and cleans up certificate directories.
AnyCert provides three flexible client setup options:
- Open your browser on any client device and navigate to the AnyCert landing page:
http://<SERVER_IP>/orhttps://<SERVER_IP>/(Served on HTTP Port 80 and standard HTTPS Port 443) - The page features a modern dark-mode interface displaying server info, HTTPS proxy port cards, and a Dynamic Connection Security Status Bar.
- The page includes Automatic CA Trust Probing: On HTTP, it explains why plain HTTP displays "Not Secure" and probes HTTPS. Once the client script installs the CA, switching to
https://<SERVER_IP>/immediately lights up the 🔒 Secure Lock! - The page includes Automatic Client OS Detection, automatically highlighting the matching download button for your OS (Windows / Linux / macOS) with a cyan
DETECTEDbadge.
Execute the installer script for your operating system with -s <SERVER_IP> for zero-prompt automated setup:
- Windows Client:
anycert-windows.bat -s <SERVER_IP>(Run as Administrator) - Linux Client (Ubuntu / Debian):
sudo bash anycert-linux.sh -s <SERVER_IP> - macOS Client:
sudo bash anycert-macos.sh -s <SERVER_IP>
- Download the Root CA certificate via HTTP or SCP:
- HTTP:
curl -s -L -o anycert-ca.crt http://<SERVER_IP>/anycert/anycert-ca.crt - SCP:
scp user@<SERVER_IP>:/etc/anycert/anycert-ca.crt ./anycert-ca.crt
- HTTP:
- Add the IP and FQDN entry to your client's
hostsfile (<SERVER_IP> <SERVER_FQDN>). - Import the CA certificate into your system trust store and browser to complete setup.
- Smart Transmission & CA Download:
- HTTP/HTTPS Curl Download (Priority 1, Password-free): During server deployment, Nginx automatically serves the Root CA, configuration, and client scripts locally on Port 80 and all SSL wrapper ports. Client scripts probe HTTP/HTTPS endpoints first for zero-password, instant distribution.
- SCP Download (Priority 2, SSH-backed): If HTTP download fails, the client automatically falls back to SCP.
- SMB Fallback (Priority 3, Specifically for Windows Server): If both HTTP and SCP fail (e.g. Windows server without SSH active), the client script will automatically fall back to the Windows SMB (Port 445) channel.
- Linux Client: Automatically checks and installs
smbclientif missing, then fetches the certificate directly. - macOS Client: Uses native
mount_smbfsto mount thec$administrative share and fetch the file. - Smart FQDN Detection: Parses remote
anycert.confdirectly to extract the FQDN.
- Linux Client: Automatically checks and installs
- Offline / Manual Copy Mode: If both SSH and SMB are disabled, choose Manual Mode to transfer
anycert-ca.crtvia USB drive, RDP, etc. The script will handle system trust and hosts configuration.
- FQDN Auto-Mapping: Automatically writes the FQDN to the client's
hostsfile. - System & Browser Trust: Imports CA certificate into system trust store (Linux handles Chrome/Firefox NSS DB, macOS handles Keychain).
- List Available HTTPS URLs: Prints both FQDN-based and IP-based HTTPS URLs (e.g.
https://mysrv:13000andhttps://192.168.1.100:13000).
Restart your browser and access your server securely via FQDN or IP:
https://<your-server-fqdn>:<port>https://<your-server-ip>:<port>
Recommended for single-host multi-service environments. If you run multiple HTTP services concurrently on the same machine (e.g., Ollama, Next.js, Vite, OpenClaw), choose Service Profile [1] Auto-Setup Nginx SSL Proxy:
- The script automatically scans active listening TCP ports on the server and lists them as tips.
- Enter the ports you wish to wrap in SSL. Nginx will automatically map them to
HTTPS Port + offset(defaults to 10000, customizable):https://mysrv:13000➔ proxies to localhttp://localhost:3000(LLMChat / Next.js)https://mysrv:21434➔ proxies to localhttp://localhost:11434(Ollama)https://mysrv:17860➔ proxies to localhttp://localhost:7860(Gradio app)
- No changes to Docker containers or original app configurations are needed. Nginx wraps them in TLS seamlessly on the host.
Dedicated Gateway / Multi-Host. This profile turns your machine into a dedicated Gateway VM/LXC (Host N) that decrypts HTTPS traffic and forwards it to other backend servers with different IPs across your LAN. There is no port offset by default — the Gateway maps HTTPS traffic 1-to-1 to backend ports. Enter the backend IP:PORT mappings directly (the script skips local port scanning):
https://gateway.demo.local:8006➔ proxies to remotehttp://172.16.1.1:8006(PVE Web on Host A)https://gateway.demo.local:3000➔ proxies to remotehttp://172.16.1.2:3000(Open WebUI on Host B)https://gateway.demo.local:11434➔ proxies to remotehttp://172.16.1.2:11434(Ollama API on Host B)https://gateway.demo.local:8080➔ proxies to remotehttp://172.16.1.3:8080(Home Assistant on Host C)https://gateway.demo.local:9090➔ proxies to remotehttp://172.16.1.4:9090(Prometheus on Host D)https://gateway.demo.local:8443➔ proxies to remotehttp://172.16.1.5:8443(Kubernetes Dashboard on Host E)https://gateway.demo.local:1880➔ proxies to remotehttp://172.16.1.6:1880(Node-RED on Host F)https://gateway.demo.local:9000➔ proxies to remotehttp://172.16.1.7:9000(Portainer on Host G)- Backend servers stay on plain HTTP — only the Gateway holds the SSL certificate. Clients connect to the single Gateway FQDN (
gateway.demo.local); the Gateway routes to any machine on any port in your LAN. Just add moreIP:PORTentries as your infrastructure grows.
💡 Multi-Host Deployment Example: Suppose you have a Gateway (Host N) plus many dedicated hosts around your LAN:
- Host A (IP:
172.16.1.1): Running PVE (8006)- Host B (IP:
172.16.1.2): Running Ollama (11434) and Open WebUI (3000)- Host C–G (IPs
172.16.1.3–172.16.1.7): Various dedicated servers (Home Assistant, Prometheus, etc.)- Host N (IP:
172.16.1.100): A clean VM/host dedicated for Nginx SSL GatewayOnly run
anycert.shon Host N (172.16.1.100) — choose Option[2], enter the full backend list (e.g.172.16.1.1:8006 172.16.1.2:3000 172.16.1.3:8080 ...) with offset0. Then run the client script on your laptop pointing to Host N's IP (172.16.1.100). Your laptop can now securely access every service viahttps://gateway.demo.local:<port>.
This profile is best when the target service already terminates HTTPS (e.g. OMV, IIS, Unraid, ESXi). anycert will automatically copy the cert and private key to the specified locations, and then run your custom service reload command to apply them.
OMV uses Nginx to serve its Web UI. Choose Service Profile [3] Custom Path and enter:
- Cert target path:
/etc/ssl/certs/openmediavault-webgui.crt - Key target path:
/etc/ssl/private/openmediavault-webgui.key - Reload command:
systemctl restart nginx
Unraid stores its SSL certificate in the USB flash configuration. Choose Service Profile [3] Custom Path and enter:
- Cert target path:
/boot/config/ssl/certs/cert.pem - Key target path:
/boot/config/ssl/certs/key.pem - Reload command:
/etc/rc.d/rc.nginx reload
ESXi hosts store their web console certificates in a fixed location. Choose Service Profile [3] Custom Path and enter:
- Cert target path:
/etc/vmware/ssl/rui.crt - Key target path:
/etc/vmware/ssl/rui.key - Reload command:
/etc/init.d/hostd restart && /etc/init.d/vpxa restart
Issues and saves certificate files in the standard directory only, and leaves configuration entirely to the user.
You can use Nginx manually as a reverse proxy to add HTTPS to local HTTP services like http://localhost:3000 (e.g. Open WebUI). Choose Service Profile [4] Generate Only to generate the cert files, then manually reference them in your Nginx config:
server {
listen 443 ssl;
server_name openwebui.local;
ssl_certificate /etc/nginx/ssl/anycert.crt;
ssl_certificate_key /etc/nginx/ssl/anycert.key;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}The corresponding fields are:
- Cert target path:
/etc/nginx/ssl/anycert.crt - Key target path:
/etc/nginx/ssl/anycert.key - Reload command:
nginx -s reload
If your server is running Proxmox VE, anycert.sh will automatically detect the PVE environment and offer an extra [5] Proxmox VE (PVE) option in the Service Profile menu. Selecting this option will automatically:
- Back up the existing PVE web proxy certificates (
/etc/pve/local/pveproxy-ssl.pemandpveproxy-ssl.key). - Overwrite them with the anycert-issued certificate and key.
- Restart the
pveproxyservice to apply changes immediately.
No manual path input or restart command is needed — the script handles the entire PVE web console (https://<ip>:8006) HTTPS certificate deployment automatically.
If your services (like Nginx or Docker containers) are running inside WSL 2, because WSL 2 is a Linux environment, you should run the Linux server script directly inside the WSL terminal instead of running the .bat file on the Windows host:
- Open your WSL terminal (e.g., Ubuntu/Debian) and run:
sudo bash anycert.sh
- When
anycert.shprompts you to confirm network configurations:- If you only want to access the WSL service from the local Windows host: Just accept the default WSL private IP address, and access it via
localhostor the FQDN. - If you need to access the WSL service from other devices on the LAN: Manually change the IP address to the physical LAN IP of your Windows host (e.g.,
192.168.1.100). This ensures the issued certificate binds to the physical IP. You will then need to configure network routing or port forwarding on the Windows host to forward traffic to WSL.
- If you only want to access the WSL service from the local Windows host: Just accept the default WSL private IP address, and access it via
WSL 2 operates on an isolated NAT network by default. To allow other devices on the same physical LAN to access your WSL services, choose one of the following two options:
Open PowerShell as Administrator on your Windows host and run:
# 1. Forward SSH Port 22 (for client downloader scripts to fetch certs & configs)
netsh interface portproxy add v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=YOUR_WSL_IP
# 2. Forward your HTTPS application Ports (e.g., 16502 and 19999)
netsh interface portproxy add v4tov4 listenport=16502 listenaddress=0.0.0.0 connectport=16502 connectaddress=YOUR_WSL_IP
netsh interface portproxy add v4tov4 listenport=19999 listenaddress=0.0.0.0 connectport=19999 connectaddress=YOUR_WSL_IP
# 3. Allow incoming traffic through Windows Defender Firewall
netsh advfirewall firewall add rule name="WSL SSH Port" dir=in action=allow protocol=TCP localport=22
netsh advfirewall firewall add rule name="WSL HTTPS Ports" dir=in action=allow protocol=TCP localport=16502,19999Note: Since WSL 2 virtual IP changes upon reboot, you will have to update the connectaddress when it changes.
WSL 2 supports sharing the Windows host IP directly, making WSL services listen directly on the physical LAN IP without any portproxy setups.
- Open Windows Explorer, go to
%userprofile%(your user folder). - Create or edit a file named
.wslconfigand add:[wsl2] networkingMode=mirrored
- Restart WSL from CMD:
wsl --shutdownand restart your WSL shell. - Allow Ports in Windows Defender Firewall:
netsh advfirewall firewall add rule name="WSL Mirrored Ports" dir=in action=allow protocol=TCP localport=22,16502
Note
About Physical Network IP Detection on Windows
When running anycert.bat on Windows Server, it automatically filters out virtual network interfaces such as Hyper-V Virtual Switch (vEthernet), WSL Virtual Switch, Tailscale, VMware, and VirtualBox network adapters. It will automatically detect and bind to the host's actual physical LAN IP address.
Q: Can I set up local certificate trust on a single computer?
A: Yes. First run the server script (anycert.bat or anycert.sh) and specify 127.0.0.1 as the server IP. On Windows, the installer will ask if you want to import the CA into the local trust store (selecting yes skips the need to run the client script). On Linux, macOS, or WSL, simply run the corresponding client script once on the same computer.
Q: Can I achieve 1:1 port forwarding (like Profile 2) on a single host with dual NICs or IP Aliases? What are the key pitfalls?
A: Yes! This is known as Single-Host Fusion Mode. By binding a secondary IP address (IP Alias / Secondary IP) to your host's network card, you can achieve 1:1 port HTTPS reverse proxying on a single machine without deploying extra VMs or LXC containers:
-
🔹 Architecture & Workflow:
- Network Setup: Assign primary
IP-A(e.g.192.168.1.100) and add a secondary virtualIP-B(e.g.192.168.1.200) to the network interface. - Service Listening: Configure backend web services to bind strictly on
IP-A:port(or127.0.0.1:port), while Nginx SSL listens onIP-B:port. - Traffic Routing: Requests to
https://IP-B:3000🔒 → decrypted by Nginx → forwarded tohttp://127.0.0.1:3000🔓 with zero port conflicts.
- Network Setup: Assign primary
-
🚨 Critical Pitfalls to Avoid:
0.0.0.0Binding Collision (EADDRINUSE): Many backend applications and Docker containers default to listening on0.0.0.0:PORT(all interfaces). If a backend service claims0.0.0.0:3000, Nginx will fail to start onIP-B:3000due to port collision. Solution: You must update the backend config or Docker port mapping to bind explicitly to127.0.0.1orIP-A.- IP Allocation & Cloud Restrictions: On LANs, ensure
IP-Bis reserved/static on your router. On cloud providers (AWS/GCP/Azure), assign a Secondary Private IP via the cloud management console. - Reboot Persistence: Secondary IPs added via temporary CLI tools (e.g. Linux
ip addr addor Windowsnetsh) will disappear upon reboot. Save them to system network configs (e.g. netplan, systemd-networkd, or Windows Registry) to survive reboots.
Q: If I already have a Soft Router (e.g. OpenWrt, pfSense, OPNSense) that issues certificates, why do I need AnyCert?
A: Their target scenarios and automation scope are completely different! Router ACME tools usually only cover certificate generation for public domains, whereas AnyCert provides a complete end-to-end solution: 100% Offline & Domain-free Issuance + Automated Nginx Proxy + One-click Cross-Platform Client Trust Automation:
- 100% Offline & Zero Domain Dependencies: Router ACME requires a registered public domain name and external DNS API credentials (e.g. Cloudflare). AnyCert works offline in isolated LANs, raw IPs (e.g.
192.168.x.x), or Tailscale VPN networks. - One-Click Automated Client Trust: Soft Routers cannot automate client-side trust installation. AnyCert provides one-click client scripts (
anycert-windows.bat,anycert-linux.sh,anycert-macos.sh) that automatically fetch the CA, install it into system & Chrome trust stores, and update local hosts. - Zero Network Topology Changes: No need to buy or configure soft router hardware—simply run AnyCert on any existing host (Windows, Linux, macOS, or Proxmox VE).
Q: Can I use AnyCert on mobile devices (iOS / Android)? How do I install the certificate?
A: Yes, absolutely! Mobile devices can fully trust AnyCert by installing anycert-ca.crt 🔒!
- 💡 Important Note on Mobile Connectivity (IP vs. FQDN):
- Recommended: Connect via IP (
https://<SERVER_IP>:xxxx): Non-rooted mobile devices cannot edit localhostsfiles. AnyCert includes server IPs in the certificate's SAN fields, so direct IP connections work securely without editing hosts! - To use FQDN domain names on mobile (
https://<FQDN>:xxxx): You must configure a Local DNS A Record pointing to the server IP on your router or local DNS server (e.g. AdGuard Home, Pi-hole, OpenWrt).
- Recommended: Connect via IP (
- 📱 iOS / iPadOS Setup:
- Open
http://<SERVER_IP>/in Safari and tap Download Root CA. - Go to iOS Settings → Profile Downloaded → Install.
- Crucial Step: Go to Settings → General → About → Certificate Trust Settings → Toggle Full Trust ON for AnyCert Root CA.
- Open
- 🤖 Android Setup:
- Open
http://<SERVER_IP>/in Chrome and downloadanycert-ca.crt. - Go to Android Settings → Security & Privacy → More Security Settings → Encryption & Credentials → Install a Certificate → CA Certificate.
- Tap "Install Anyway" and select the downloaded
anycert-ca.crtfile.
- Open
sudo bash anycert.sh -u
# Or Windows Server
anycert.bat -uRemoves generated certificates and restores original configurations (including removing Nginx proxies).
sudo bash anycert-linux.sh -u
# Or macOS Client
sudo bash anycert-macos.sh -u
# Or Windows Client
anycert-windows.bat -uThis will display a list of registered servers and allow you to selectively or completely remove the hosts entries and imported CA certificates.
This project is licensed under the MIT License.
Author: anomixer