Skip to content
anomixerPublic

About

Trusted HTTPS for local dev, private networks, and enterprise self-hosting. (本機開發、內網與企業自架服務的受信 HTTPS 工具)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

anycert

anycert — Trusted HTTPS for Local Dev, Private Networks, and Enterprise Self-Hosting

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)


Quick Start

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 Administrator

Each 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>.


Why anycert?

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 (With red warning) ✅ Yes ✅ Yes ✅ Yes (Limited to *.ts.net) ✅ Yes
IP Access ⚠️ Yes (With red warning) ❌ No ❌ No ❌ No ✅ Yes (SAN contains multiple IPs)
Complexity None High Medium Medium Low (One command server, one command client)

Best Use Cases

  • 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.net domains.
  • 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.

anycert vs. mkcert

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 ⚠️ Yes (Go to build OR pre-built binary) ✅ 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.


Key Concepts

💡 10-Year CA vs. 825-Day Server Cert

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:

  1. Root CA (10 years): Installed and trusted on the client device. It remains unchanged.
  2. 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.

💡 Design Philosophy: Port Offsetting vs. Subdomains

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.


🔒 Why Local HTTPS Matters

Using HTTPS on a local area network (LAN) provides critical benefits beyond simply eliminating browser warning screens:

1. Enabling Modern Browser APIs (Secure Contexts Enforcement)

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.

2. Protecting Credentials and Tokens from Local Sniffing

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.

3. Preventing Blocked Downloads (Insecure Downloads Policy)

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.

Supported Environments & OS Compatibility

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:

1. Server Setup Compatibility

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)

2. Client Trust Automation Compatibility

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 Description

Server-side (Generator & Installer)

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

Client-side (Downloader & Truster)

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

Installation Steps

Step 1 — On the Server (Generate Certs)

Linux (including WSL) / macOS Server:

Clone this repo and run anycert.sh:

git clone https://github.com/anomixer/anycert.git
cd anycert
sudo bash anycert.sh

The script will:

  1. 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_name rules.
  2. 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 + offset to HTTP 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:PORT mappings, and defaults to no port offset (1-to-1 mapping, e.g., HTTPS 3000 proxies to backend 3000 directly).
    • [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.

💡 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.sh or anycert-linux.sh) locally on this server. Specify 127.0.0.1 as 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
Loading

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
Loading

💡 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 Gateway

Deployment Steps:

  1. Server Setup: Only run anycert.sh on 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, and 11434 and encrypt-forward them to their backends.
  2. Client Setup: Run the client setup script on your work laptop, and specify Host C's IP 172.16.1.3 as the Server IP.
  3. Result: Your laptop can now securely access Open WebUI via https://gateway.demo.local:3000 and PVE via https://gateway.demo.local:8006 without 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
Loading

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
Loading

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
Loading

Windows Server:

Run Command Prompt (cmd) as Administrator and execute:

anycert.bat

The 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:

  1. 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 add 8080 and remove 3000 from Nginx proxy wrappers. Nginx configuration will reload automatically.
  2. Renew/Regenerate SSL Certificates: Keeps the existing Nginx proxy ports configuration but renews expired server certificates.
  3. Uninstall: Completely restores the original settings and cleans up certificate directories.

Step 2 — On Each Client (Trust the CA)

AnyCert provides three flexible client setup options:

🌟 Option A: Web Browser One-Click Setup (Recommended ⭐)

  1. Open your browser on any client device and navigate to the AnyCert landing page: http://<SERVER_IP>/ or https://<SERVER_IP>/ (Served on HTTP Port 80 and standard HTTPS Port 443)
  2. The page features a modern dark-mode interface displaying server info, HTTPS proxy port cards, and a Dynamic Connection Security Status Bar.
  3. 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!
  4. The page includes Automatic Client OS Detection, automatically highlighting the matching download button for your OS (Windows / Linux / macOS) with a cyan DETECTED badge.

⚡ Option B: Automatic Client Script (CLI / Remote)

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>

🛠️ Option C: Manual Setup

  1. 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
  2. Add the IP and FQDN entry to your client's hosts file (<SERVER_IP> <SERVER_FQDN>).
  3. Import the CA certificate into your system trust store and browser to complete setup.

💡 Client Automated Script Mechanics:

  1. 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 smbclient if missing, then fetches the certificate directly.
      • macOS Client: Uses native mount_smbfs to mount the c$ administrative share and fetch the file.
      • Smart FQDN Detection: Parses remote anycert.conf directly to extract the FQDN.
    • Offline / Manual Copy Mode: If both SSH and SMB are disabled, choose Manual Mode to transfer anycert-ca.crt via USB drive, RDP, etc. The script will handle system trust and hosts configuration.
  2. FQDN Auto-Mapping: Automatically writes the FQDN to the client's hosts file.
  3. System & Browser Trust: Imports CA certificate into system trust store (Linux handles Chrome/Firefox NSS DB, macOS handles Keychain).
  4. List Available HTTPS URLs: Prints both FQDN-based and IP-based HTTPS URLs (e.g. https://mysrv:13000 and https://192.168.1.100:13000).

Step 3 — Secure HTTPS Connection 🔒

Restart your browser and access your server securely via FQDN or IP:

  • https://<your-server-fqdn>:<port>
  • https://<your-server-ip>:<port>

Deployment Examples

1. Nginx Automated Reverse Proxy (Profile [1] — Auto-Setup Nginx SSL Proxy)

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 local http://localhost:3000 (LLMChat / Next.js)
    • https://mysrv:21434 ➔ proxies to local http://localhost:11434 (Ollama)
    • https://mysrv:17860 ➔ proxies to local http://localhost:7860 (Gradio app)
  • No changes to Docker containers or original app configurations are needed. Nginx wraps them in TLS seamlessly on the host.

2. Nginx SSL Gateway (Profile [2] — Auto-Setup Nginx SSL Gateway)

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 remote http://172.16.1.1:8006 (PVE Web on Host A)
  • https://gateway.demo.local:3000 ➔ proxies to remote http://172.16.1.2:3000 (Open WebUI on Host B)
  • https://gateway.demo.local:11434 ➔ proxies to remote http://172.16.1.2:11434 (Ollama API on Host B)
  • https://gateway.demo.local:8080 ➔ proxies to remote http://172.16.1.3:8080 (Home Assistant on Host C)
  • https://gateway.demo.local:9090 ➔ proxies to remote http://172.16.1.4:9090 (Prometheus on Host D)
  • https://gateway.demo.local:8443 ➔ proxies to remote http://172.16.1.5:8443 (Kubernetes Dashboard on Host E)
  • https://gateway.demo.local:1880 ➔ proxies to remote http://172.16.1.6:1880 (Node-RED on Host F)
  • https://gateway.demo.local:9000 ➔ proxies to remote http://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 more IP:PORT entries 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 Gateway

Only run anycert.sh on 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 offset 0. 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 via https://gateway.demo.local:<port>.

3. Custom Path (Profile [3])

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.

3.1 OpenMediaVault (OMV)

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

3.2 Unraid

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

3.3 VMware ESXi

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

4. Generate Only (Profile [4] — Manual Deploy)

Issues and saves certificate files in the standard directory only, and leaves configuration entirely to the user.

4.1 Nginx Manual Reverse Proxy

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

5. Proxmox VE (Profile [5] — Proxmox VE)

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.pem and pveproxy-ssl.key).
  • Overwrite them with the anycert-issued certificate and key.
  • Restart the pveproxy service 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.

6. WSL Deployment (Profile [1] — Auto-Setup Nginx SSL Proxy)

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:

  1. Open your WSL terminal (e.g., Ubuntu/Debian) and run:
    sudo bash anycert.sh
  2. When anycert.sh prompts 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 localhost or 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.

Connecting from Other LAN Devices to WSL 2:

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:

Option A: Configure Port Forwarding via Windows Portproxy (For NAT mode)

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,19999

Note: Since WSL 2 virtual IP changes upon reboot, you will have to update the connectaddress when it changes.

Option B: Enable WSL 2 Mirrored Networking Mode (Easiest, Windows 11 22H2+)

WSL 2 supports sharing the Windows host IP directly, making WSL services listen directly on the physical LAN IP without any portproxy setups.

  1. Open Windows Explorer, go to %userprofile% (your user folder).
  2. Create or edit a file named .wslconfig and add:
    [wsl2]
    networkingMode=mirrored
  3. Restart WSL from CMD: wsl --shutdown and restart your WSL shell.
  4. 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.


Frequently Asked Questions (FAQ)

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:

    1. Network Setup: Assign primary IP-A (e.g. 192.168.1.100) and add a secondary virtual IP-B (e.g. 192.168.1.200) to the network interface.
    2. Service Listening: Configure backend web services to bind strictly on IP-A:port (or 127.0.0.1:port), while Nginx SSL listens on IP-B:port.
    3. Traffic Routing: Requests to https://IP-B:3000 🔒 → decrypted by Nginx → forwarded to http://127.0.0.1:3000 🔓 with zero port conflicts.
  • 🚨 Critical Pitfalls to Avoid:

    1. 0.0.0.0 Binding Collision (EADDRINUSE): Many backend applications and Docker containers default to listening on 0.0.0.0:PORT (all interfaces). If a backend service claims 0.0.0.0:3000, Nginx will fail to start on IP-B:3000 due to port collision. Solution: You must update the backend config or Docker port mapping to bind explicitly to 127.0.0.1 or IP-A.
    2. IP Allocation & Cloud Restrictions: On LANs, ensure IP-B is reserved/static on your router. On cloud providers (AWS/GCP/Azure), assign a Secondary Private IP via the cloud management console.
    3. Reboot Persistence: Secondary IPs added via temporary CLI tools (e.g. Linux ip addr add or Windows netsh) 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 local hosts files. 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).
  • 📱 iOS / iPadOS Setup:
    1. Open http://<SERVER_IP>/ in Safari and tap Download Root CA.
    2. Go to iOS Settings → Profile Downloaded → Install.
    3. Crucial Step: Go to Settings → General → About → Certificate Trust Settings → Toggle Full Trust ON for AnyCert Root CA.
  • 🤖 Android Setup:
    1. Open http://<SERVER_IP>/ in Chrome and download anycert-ca.crt.
    2. Go to Android Settings → Security & Privacy → More Security Settings → Encryption & Credentials → Install a Certificate → CA Certificate.
    3. Tap "Install Anyway" and select the downloaded anycert-ca.crt file.

Uninstall

Server-side

sudo bash anycert.sh -u
# Or Windows Server
anycert.bat -u

Removes generated certificates and restores original configurations (including removing Nginx proxies).

Client-side

sudo bash anycert-linux.sh -u
# Or macOS Client
sudo bash anycert-macos.sh -u
# Or Windows Client
anycert-windows.bat -u

This will display a list of registered servers and allow you to selectively or completely remove the hosts entries and imported CA certificates.


📜 License

This project is licensed under the MIT License.
Author: anomixer

About

Trusted HTTPS for local dev, private networks, and enterprise self-hosting. (本機開發、內網與企業自架服務的受信 HTTPS 工具)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages