Documentation

How ManageMyCert works.

Everything you need to know to monitor, renew, and deploy SSL/TLS certificates.

Create an account

Sign up with your email and a password, or click Continue with Google. Please note that your password is never stored on our servers.

Google sign-in configuration

Google sign-in uses Google Identity Services on the portal and verifies the Google ID token server-side.

Google sign-in (via portal)

Continue with Google opens portal.managemycert.com, where you click the Google Identity Services button. The session is created on the portal host, which avoids Firebase popup/iframe storage issues in modern browsers. After Google approves access, you are signed into the portal automatically.

Organization / workspace (optional)

This field becomes the display name of your new workspace. Leading and trailing spaces are removed; letters and capitalization are kept exactly as you type (Acme Inc and acme inc are stored as two different names). Signing up does not match you to an existing company by this label — teammates are invited by email from Team after you are in the portal. Leave the field empty to get a personal workspace with an automatic name.

Adding your first domain

From the portal, click + Add domain and enter a hostname. We'll do an immediate SSL inspection — no installation, no SDK, no config files. We also probe the public site over HTTP(S) to detect common hosting stacks (WordPress, cPanel, Plesk, Shopify, Wix, etc.) and show hints before you confirm.

After ownership is verified, open the domain's Let's Encrypt tab to issue a free certificate via DNS — no SSH key required — then install via your hosting panel API or download ZIP.

Verifying ownership

Before we activate monitoring on a domain, you have to prove you control it. Choose one method:

Method 1 — DNS TXT record

Add a TXT record on the domain you're adding:

_managemycert-verify.example.com.  IN TXT  "mmc-<your-token>"

Method 2 — A record on a verify subdomain

Point a unique subdomain at our verifier IP:

<your-token>.verify.managemycert.com.  IN A  198.51.100.42

After saving the record, hit I've added it in the portal — we'll do a live DNS lookup and unlock monitoring.

Note: this verification TXT is for ManageMyCert ownership only. When you issue a Let's Encrypt certificate on the Let's Encrypt tab, you'll add a separate _acme-challenge TXT record — see Let's Encrypt via DNS.

Hosting detection

When you add a domain, ManageMyCert fetches the public homepage and inspects response headers and HTML for signatures of common platforms: WordPress, Shopify, Wix, Squarespace, cPanel, Plesk, Cloudflare, Drupal, Joomla, Magento, and typical web servers (Nginx, Apache, Caddy).

  • Badges appear on the add-domain review screen and on the domain Overview tab after verification.
  • Hosted SaaS (Shopify, Wix, Squarespace) — TLS is managed by the vendor; use Monitor only or install certs through their admin panel.
  • cPanel / Plesk / Cloudflare — connect API credentials under Install certificate for automatic push, or download the certificate ZIP and upload manually.
  • Self-managed VPS — issue via DNS, download the ZIP, or configure optional SSH deploy on Renew & deploy.

On the Renew & deploy tab, Detect platform (with SSH credentials) combines HTTP hints with a live server probe for webroot paths, distro, and reload commands.

Notification gateways

Expiry and renewal alerts can go out on email, SMS, Slack, and third-party integrations. Open Settings → Notification gateways in the portal:

  • Email: Optional SMTP (bring your own). Without a gateway, alerts use the default platform mail server.
  • SMS & Slack: Bring your own (Twilio, custom REST GET/POST, or Slack incoming webhook).
  • Integrations: Search and connect Microsoft Teams, Opsgenie, Jira, ServiceNow, Zendesk, Freshservice, Zoho Desk, or a generic webhook. Each integration has a guided form and Send test so you can verify delivery before going live.

Gateway secrets are encrypted at rest (AES-256-GCM). Use alert rules with the matching channel (e.g. teams, opsgenie) after you connect the integration.

General settings

Workspace admins can set defaults under Settings → General (per organization):

  • Monitor interval — how often verified domains are SSL-inspected (minutes).
  • Alert cooldown — minimum hours before the same alert rule fires again for a domain.
  • Delivery retries — how many extra attempts when a gateway send fails.
  • Retry delay — minutes to wait between retry attempts.

Alert templates

Reusable messages with variables: {{domain}}, {{days_left}}, {{issuer}}, {{expires}}, {{host}}.

Alert rules

Match a (domain or all-domains) → channel → days-before-expiry → recipients. Multiple rules can fire for one domain.

Pick a deployment mode

Each domain has a Let's Encrypt tab (DNS issuance, no SSH) and a Renew & deploy tab (automation mode + optional SSH push). Choose one deployment mode on Renew & deploy:

ModeIssuanceSSH key?
Monitor onlyNone — we watch expiry and alert you.No
Let's Encrypt (DNS)DNS-01 on ManageMyCert servers; download ZIP anytime.No (optional for push)
Auto-renew (SSH)HTTP-01 on your server via SSH; auto-renew ~30 days before expiry.Yes
Upload & deployYou upload PEM/PFX from any CA; install via hosting API or optional SSH.Optional

Recommended for most customers: verify the domain, issue on the Let's Encrypt tab (DNS TXT), download the ZIP, install in your hosting panel or web server. Add SSH on Renew & deploy only if you want ManageMyCert to push the stored cert for you.

Let's Encrypt via DNS (recommended)

The easiest path: no SSH key, no port 80, no webroot. ManageMyCert runs the ACME DNS-01 challenge on our servers, stores the issued certificate encrypted in the database, and lets you download a ZIP whenever you need it.

Step-by-step

  1. Add the domain and complete ownership verification (ManageMyCert TXT record).
  2. Open the domain → Let's Encrypt tab.
  3. Click Get certificate — start DNS challenge. The portal shows one or more ACME TXT records (one per hostname / SAN).
  4. At your DNS provider, add each TXT record. Example for example.com:
    Host / name:  _acme-challenge
    Type:         TXT
    Value:        (paste the long string from the portal)
    
    FQDN:         _acme-challenge.example.com
  5. Wait 1–10 minutes for DNS propagation, then click Issue certificate.
  6. Download the ZIP from Your certificates — see Download certificate ZIP.
  7. Install on your server or hosting panel. Optionally configure SSH on Renew & deploy and click Deploy now to push the stored cert.

The portal checks public DNS for each _acme-challenge TXT value before contacting Let's Encrypt. If propagation is slow, wait and click Issue certificate again — you don't need to restart the challenge unless you cancelled it.

Two different TXT records are normal: _managemycert-verify… proves you own the domain to us; _acme-challenge… proves it to Let's Encrypt when issuing. You can leave the verification record in place.

Download certificate ZIP

Every DNS-issued certificate is stored encrypted (AES-256-GCM). Download the bundle any time from the Let's Encrypt tab — no need to re-issue unless you're within the renewal window (see below).

File in ZIPUse
cert.pemLeaf certificate only.
chain.pemIntermediate chain (no leaf).
fullchain.pemLeaf + chain — use for Nginx ssl_certificate, Apache SSLCertificateFile, etc.
privkey.pemPrivate key — keep secret; 0600 permissions on disk.
README.txtShort install notes and generation timestamp.

The same four PEM filenames are used when ManageMyCert deploys via SSH. Custom filenames can be configured on the deploy form.

Hosting panel install (API)

The recommended install path after DNS issuance: connect your hosting control panel with API credentials — no SSH private key required. ManageMyCert detects your platform when you add a domain and suggests the right flow on Renew & deploy → Install certificate.

PlatformInstall method
cPanelAPI token with SSL install permission — we call UAPI SSL/install_ssl.
PleskAdmin/reseller username + password — certificate uploaded via Plesk REST API.
CloudflareAPI token — uploads or updates a custom edge certificate on your zone via POST/PATCH /zones/{id}/custom_certificates. Requires Business/Enterprise or Advanced Certificate Manager. Zone ID is auto-detected from your domain.
WordPress, Drupal, Joomla, MagentoNo standard SSL upload API — download ZIP and install on your web server or host panel.
Shopify, Wix, SquarespaceVendor-managed TLS — Monitor only; use their admin tools if needed.

API tokens and passwords are stored with AES-256-GCM encryption (see Optional SSH & encryption). They are decrypted only during a deploy job, never written to logs, and shown masked in the portal after save.

Cloudflare note: Custom certificates are installed on Cloudflare's edge (what visitors see). If your origin is orange-cloud proxied, you may still need the ZIP on the origin for Full (strict) mode. Universal SSL on the free plan is managed by Cloudflare and cannot be replaced with your own Let's Encrypt upload via this API.

Uploaded certificates (DigiCert, Sectigo, etc.) can be installed via the same hosting API — there is no ZIP download for third-party CAs, only for Let's Encrypt issued on ManageMyCert.

Optional SSH & encryption

SSH deploy is optional and tucked under Advanced in the portal. Most customers use DNS issuance + hosting API or ZIP download instead. If you do provide SSH access for a self-managed VPS:

  • At rest — SSH private keys, API tokens, certificate private keys, and gateway secrets are encrypted with AES-256-GCM using SECRETS_ENCRYPTION_KEY (32-byte hex in your server .env).
  • In use — Keys are decrypted only in memory for the duration of a deploy job (typically seconds), then discarded. They are not stored in plaintext on disk.
  • If our database were compromised — An attacker would still need your SECRETS_ENCRYPTION_KEY from the application server to decrypt blobs. Without both database and key, ciphertext is useless.
  • Scope — Use a dedicated deploy user with limited sudo (see SSH user guide). API tokens should grant SSL install only, not full account access.
  • Never logged — Private keys and API secrets are excluded from audit logs and activity messages.
# Encrypted blob format (hex):
iv(12 bytes):authTag(16 bytes):ciphertext

# Generate a production encryption key:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

30-day issuance window

To avoid unnecessary re-issuance and Let's Encrypt rate limits, ManageMyCert blocks new DNS issuance when a valid Let's Encrypt certificate is already on file with more than 30 days remaining (configurable via ACME_ISSUE_MIN_DAYS_LEFT in .env).

  • Download anytime — existing stored certs are always available as ZIP.
  • Re-issue — when ≤30 days remain (or no valid stored cert exists), use the Let's Encrypt tab again with a fresh DNS TXT challenge.
  • Auto-renew (SSH mode) — the background worker still auto-renews only acme_auto domains with SSH + HTTP-01. DNS mode is manual re-issue; expiry alerts still fire on the normal schedule.

Create SSH user & key

Create a dedicated deployment user on each destination host (don't reuse personal logins). On your laptop / admin workstation, generate one keypair you can install on every server:

ssh-keygen -t ed25519 -f ./mmc-deploy-ed25519 -C "managemycert deploy"
# files produced:
#   mmc-deploy-ed25519       ← private key, paste into the portal
#   mmc-deploy-ed25519.pub   ← public key, install on every server below

On each destination server (run as root or via sudo):

sudo useradd --system --create-home --shell /bin/bash mmc-deploy
sudo install -d -m 700 -o mmc-deploy -g mmc-deploy /home/mmc-deploy/.ssh
# put the .pub from the laptop on the server, then:
sudo tee -a /home/mmc-deploy/.ssh/authorized_keys < mmc-deploy-ed25519.pub
sudo chown mmc-deploy:mmc-deploy /home/mmc-deploy/.ssh/authorized_keys
sudo chmod 600 /home/mmc-deploy/.ssh/authorized_keys

In the portal, paste the private key once into the deploy form (or per extra target). Pasting only the private key is enough for authentication, but the portal also needs host, username, port, certificate directories, and (for Auto-renew) either a webroot or the standalone listener — see below. Verify locally first with ssh -i ./mmc-deploy-ed25519 mmc-deploy@SERVER 'echo ok'.

Walkthrough: 2 servers, same certificate

Common case: one Let's Encrypt cert installed on Server A and Server B. Use a single key on both, or two keys — both work.

WhereWhat you do
Your laptopssh-keygen once → keep the private key file safe.
Server ACreate mmc-deploy, install the .pub in authorized_keys. Allow write to the cert directories (or enable sudo install).
Server BSame steps as A. Reuse the same .pub if you want one key for both.
Portal · primary deployServer A host + username + paste the private key + cert paths + reload commands.
Portal · extra targetClick Add server: Server B host + username + (same or different) private key + Server B's cert paths + reload commands.
Portal · webrootFor Auto-renew, set the webroot of the host listed first (or enable Standalone listener if neither host runs a web server). HTTP-01 challenges run against the first target; the issued cert is pushed to every target.

Once both targets are saved, click Renew now; the Activity log shows the trail per target.

SSH deployment

By default the portal pushes cert.pem, key.pem, chain.pem, and fullchain.pem over SFTP into every certificate directory you list. Under Renew & deploy you can enable Use custom file names if your Nginx, Apache, or mail config already references different paths (e.g. server.crt / privkey.pem). The form always shows which four files will be written before you save.

Upload & deploy accepts pasted PEM text or a .pfx / .p12 file (with password if needed). We extract the certificate and key server-side, validate the hostname, then deploy using your chosen file names.

/etc/nginx/ssl/example.com
/etc/haproxy/certs/example.com
/usr/local/etc/opensips/tls/letsencrypt

Reload/restart commands also go one per line and run sequentially after all files are written:

sudo -n systemctl reload nginx
sudo -n systemctl restart haproxy
sudo -n systemctl restart opensips

Important: ManageMyCert runs reload commands as the SSH user you connect with, never as root. systemctl reload/restart almost always requires root, so you must prefix with sudo -n (non-interactive) and grant that user permission via sudoers — see Reload/restart sudoers.

What files do we install?

For every certificate directory you list, ManageMyCert writes four files (PEM, UTF-8). Filenames are fixed and match the convention used by Let's Encrypt / certbot:

FileModeContents
cert.pem0644The leaf certificate only.
key.pem0600The private key for the leaf certificate.
chain.pem0644The issuing intermediate(s), no leaf.
fullchain.pem0644Leaf + intermediate(s) concatenated; what most servers want.

Common mappings in service config files:

# Nginx
ssl_certificate     /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/key.pem;

# Apache
SSLCertificateFile      /etc/apache2/ssl/example.com/fullchain.pem
SSLCertificateKeyFile   /etc/apache2/ssl/example.com/key.pem

# HAProxy (combined PEM)
# Many setups use one file holding fullchain + key. Either point HAProxy at fullchain.pem
# and use a `bind ssl crt-list` that names key.pem, or post-process with your own reload
# command (a one-liner `cat fullchain.pem key.pem > combined.pem`).

# OpenSIPS (TLS module / tls_mgm)
tls_certificate    "/usr/local/etc/opensips/tls/letsencrypt/fullchain.pem"
tls_private_key    "/usr/local/etc/opensips/tls/letsencrypt/key.pem"
tls_ca_list        "/usr/local/etc/opensips/tls/letsencrypt/chain.pem"

# Postfix
smtpd_tls_cert_file = /etc/postfix/tls/example.com/fullchain.pem
smtpd_tls_key_file  = /etc/postfix/tls/example.com/key.pem

# Dovecot
ssl_cert = </etc/dovecot/tls/fullchain.pem
ssl_key  = </etc/dovecot/tls/key.pem

With Use sudo for cert install on, the same four files are placed via sudo cp; with a chown set, chown is run last (e.g. opensips:opensips) so the daemon can read them.

Reload/restart sudoers (giving service control to the deploy user)

Reload commands run on the server as the SSH user you configured in the portal (e.g. mmc-deploy) — not as root. Most service controls (systemctl, service, /etc/init.d/...) need root, so the command will fail with messages like:

Failed to restart opensips.service: Interactive authentication required.

Two-step fix on the target server:

  1. Add a sudoers entry for only the exact commands ManageMyCert should be allowed to run.
  2. Prefix the reload commands in the portal with sudo -n so they actually use sudo.

Edit a per-user sudoers file (run as root):

sudo visudo -f /etc/sudoers.d/mmc-deploy

Paste an entry that allows only the service controls you actually need. Examples:

# Nginx + HAProxy
mmc-deploy ALL=(root) NOPASSWD: /bin/systemctl reload nginx, /bin/systemctl restart haproxy
Defaults:mmc-deploy !requiretty
# OpenSIPS (reload first, restart as fallback)
mmc-deploy ALL=(root) NOPASSWD: /bin/systemctl reload opensips, /bin/systemctl restart opensips
Defaults:mmc-deploy !requiretty
# Postfix + Dovecot
mmc-deploy ALL=(root) NOPASSWD: /bin/systemctl reload postfix, /bin/systemctl restart dovecot
Defaults:mmc-deploy !requiretty

Notes on the syntax:

  • NOPASSWD is required so non-interactive runs don't prompt for a password.
  • Defaults:<user> !requiretty is required so sudo works when there is no terminal (the SSH session ManageMyCert opens has none for these commands).
  • List only the binaries you want to allow. The path must match what's on your server — check with which systemctl (often /bin/systemctl on Debian/Ubuntu, /usr/bin/systemctl on CentOS/RHEL).
  • The command in sudoers must match the command the portal runs exactly (same args). E.g. /bin/systemctl reload nginx in sudoers means the portal must run that exact line, not systemctl reload nginx.service.

Then in the portal's Reload/restart commands, use sudo -n:

sudo -n systemctl reload nginx
sudo -n systemctl restart opensips

Verify on the server before triggering a renewal:

sudo -u mmc-deploy sudo -n systemctl reload nginx
sudo -u mmc-deploy sudo -n systemctl restart opensips

Both lines should print no output and exit 0. If either prompts for a password or says Interactive authentication required, fix the sudoers entry first.

Installing into root-owned directories (OpenSIPS, Nginx, etc.)

Many services (OpenSIPS at /usr/local/etc/opensips/tls, Nginx at /etc/nginx/ssl, Postfix at /etc/postfix/tls, dovecot, exim, postgres, …) keep cert directories root-owned. The deploy user can't write there directly.

Turn on Use sudo for cert install (root-owned directories) on the domain's Renew & deploy tab (also available per extra target). Then ManageMyCert:

  1. SFTP-stages the four PEM files in ~/.mmc-stage-XXXX/ on the SSH user's home (mode 700).
  2. Runs one command per cert directory: sudo -n sh -c "mkdir -p <path> && cp -f stage/* <path>/ && chmod 600 key.pem && chmod 644 …".
  3. Optionally chown owner:group if you set it (e.g. opensips:opensips).
  4. Removes the staging directory.

Sudoers entry on the target server (no password, no tty), simplest form:

mmc-deploy ALL=(root) NOPASSWD: /bin/sh
Defaults:mmc-deploy !requiretty

Locked-down alternative limited to the exact tools we use:

mmc-deploy ALL=(root) NOPASSWD: /bin/mkdir, /bin/cp, /bin/chmod, /bin/chown, /bin/rm
Defaults:mmc-deploy !requiretty

For OpenSIPS specifically, set Set owner:group to opensips:opensips if the binary runs as that user, then add sudo systemctl reload opensips as a reload command (also covered by the entries above).

Multiple SSH targets

For load-balanced clusters or hosts that need different paths/commands, add extra deployment targets on the domain's Renew & deploy tab. When at least one target exists, only those rows are used for SSH (the primary fields above are ignored). HTTP-01 ACME challenges run against the first target in sort order; after a successful issue or upload, the new material is pushed to every target. Each target carries its own SSH user, key, certificate directories, reload commands, sudo toggle, and chown setting.

Detect platform (auto-fill deploy settings)

On the domain's Renew & deploy tab, click Detect platform after entering SSH host, username, and key. ManageMyCert combines:

  • HTTP scan — CMS hints (WordPress, Shopify, Drupal, etc.) from public page headers and HTML.
  • SSH scan — OS (/etc/os-release), active web server (Nginx/Apache/Caddy), Apache/Nginx document roots, WordPress install paths.

Results appear as badges (OS, web server, CMS). Click Apply suggestions to pre-fill certificate paths, reload commands, and webroot — then review and Save deployment settings. Use Test SSH first if detection fails. Hosted platforms (Shopify, Wix, Squarespace) are flagged — SSH deploy does not apply there.

Extra deployment targets (load balancers, standby nodes) have their own Detect, Test SSH, and Fix ACME redirect actions per row. Each target stores its own detected platform snapshot and last deploy status (OK / Partial / Failed).

Fix ACME redirect (primary or per-target) patches Apache/Nginx so /.well-known/acme-challenge/ is not redirected to HTTPS. Config files are backed up as *.mmc-backup-* before changes. Requires shell exec and often Use sudo for editing /etc/apache2 or /etc/nginx.

Multi-server deploy: when pushing to several targets, ManageMyCert continues after a single-server failure. If at least one target succeeds, the certificate is saved; failures are logged per target. The domain shows Partial deploy status until all targets succeed on a later run.

The Site uptime tab shows a 3D probe timeline (24h / 7d / 30d). Hover any bar for the exact check datetime, HTTP status, response time, and whether HTTPS or HTTP succeeded.

HTTP-01: which mode should I pick?

Auto-renew uses Let's Encrypt's HTTP-01 challenge. Pick the mode that matches the host the public DNS record points to:

  • Webroot — Nginx, Apache, Caddy, or any other web server is already serving HTTP. Best for websites.
  • Standalone HTTP listener — no web server is running on that host (OpenSIPS, mail, VPN, RDP gateway, database, internal API, etc.). ManageMyCert briefly starts a tiny HTTP listener over SSH for the few seconds Let's Encrypt needs.
  • No SSH access — see No SSH access below; use Monitor only or Upload & deploy.

HTTP-01 webroot path

The webroot is the directory served by your existing web server at:

http://your-domain/.well-known/acme-challenge/<token>

If Nginx serves example.com from /var/www/example.com/public, use that directory. If Apache serves from /var/www/html, use /var/www/html. ManageMyCert writes only temporary challenge files under .well-known/acme-challenge/ using SFTP (no shell exec needed; works with SFTP-only / ForceCommand internal-sftp users).

The deploy user must be able to create <webroot>/.well-known/acme-challenge. Typical fix on the server:

sudo mkdir -p /var/www/html/.well-known/acme-challenge
sudo chown -R mmc-deploy:www-data /var/www/html/.well-known
sudo chmod -R u+rwX,g+rX /var/www/html/.well-known

Or use a folder under the deploy user's home (e.g. /home/mmc-deploy/acme-webroot) as the webroot, and add a small Nginx/Apache alias for /.well-known/acme-challenge/:

# Nginx
location ^~ /.well-known/acme-challenge/ {
    alias /home/mmc-deploy/acme-webroot/.well-known/acme-challenge/;
    default_type "text/plain";
}

The webroot is not where the final certificate lives; that's set by Certificate directories on server.

HTTP→HTTPS redirect blocks renewal

A very common renewal failure looks like:

Renewal for example.com failed: Could not fetch http://example.com/.well-known/acme-challenge/<token> …
Underlying: HTTP 301 from http://example.com/.well-known/acme-challenge/…

What it means: ManageMyCert wrote the challenge file to your webroot, but when the validator (and Let's Encrypt) request http://your-domain/.well-known/acme-challenge/<token> on port 80, Apache or Nginx returns 301/302 to HTTPS instead of 200 with the token text. HTTP-01 must work over plain HTTP — a site-wide "redirect everything to HTTPS" rule breaks renewal even if HTTPS and the webroot path are otherwise correct.

Fix (Apache on port 80): exclude the ACME path before your redirect rule. Example for webroot /var/www/html/mytestwebsite.com:

<VirtualHost *:80>
    DocumentRoot /var/www/html/mytestwebsite.com

    RewriteEngine on
    RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

If you use Redirect permanent / https://…, switch to conditional rewrites as above, or add a separate <Location /.well-known/acme-challenge> that is not redirected. Reload Apache: sudo systemctl reload apache2.

Fix (Nginx on port 80):

server {
    listen 80;
    server_name example.com;
    root /var/www/html/example.com;

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

Verify before retrying renewal:

# Must show HTTP/1.1 200 (not 301). Place a test file first:
echo test | sudo tee /var/www/html/mytestwebsite.com/.well-known/acme-challenge/ping
curl -I http://mytestwebsite.com/.well-known/acme-challenge/ping

Do not enable Standalone HTTP listener while Apache/Nginx already owns port 80 — fix the redirect exception instead. Standalone is for hosts with no web server on that port.

Sudo for cert install only affects writing certificate files after issuance; it does not change how Apache serves HTTP-01 challenges.

HTTP-01 standalone (no web server)

Enable Use standalone HTTP listener on the domain's Renew & deploy tab. ManageMyCert pushes a tiny Python script via SFTP, runs it for the duration of the challenge on the port you choose (default 80), then stops it and removes the temporary files. Nothing is left running between renewals.

Requirements on the target host:

  • python3 (or python) installed and on PATH.
  • The SSH user can run a remote shell (cannot be SFTP-only) and the chosen port can be bound on 0.0.0.0.
  • The chosen port reachable from the public internet on the hostname being issued. Let's Encrypt requires port 80 publicly; if a firewall forwards 80 → 8080, set the listener port to 8080.
  • Nothing else is listening on that port — check with ss -tlnp | grep ':80'.

Port 80 is privileged on Linux. Use one of these (recommended order):

# Best: grant python the ability to bind low ports once.
sudo setcap cap_net_bind_service=+ep $(readlink -f $(command -v python3))
# Or: run via sudo. Enable "Use sudo" in the portal and add a sudoers line:
mmc-deploy ALL=(root) NOPASSWD: /usr/bin/python3, /bin/sh
Defaults:mmc-deploy !requiretty
# Or: forward 80 → 8080 with iptables and set listener port to 8080 in the portal.
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Auto-renew with SSH + HTTP-01

Choose Auto-renew (SSH) on Renew & deploy when ManageMyCert should log into your server for both validation and installation. This mode uses Let's Encrypt HTTP-01 (port 80 or webroot), not DNS. Configure SSH, webroot or standalone listener, then toggle Enable auto-renew. About 30 days before expiry, the worker requests a new certificate, validates via HTTP, installs PEM files into every configured directory, and runs reload commands across all targets.

If you don't want to provide an SSH key, use the Let's Encrypt tab instead (DNS issuance) and install the downloaded ZIP yourself.

After every attempt — manual or scheduled — ManageMyCert sends a notification through the channel(s) selected on the domain and writes a structured event to the audit log. See Logs & notifications.

Manual upload

For non-Let's Encrypt CAs (DigiCert, Sectigo, ZeroSSL, Google, internal PKI…) pick Upload & deploy. Paste the PEM bundle (cert + key, plus chain if available) under the domain's Renew & deploy tab; the portal then deploys it to every target the same way as auto-renew. Re-deploy any time by uploading a new bundle.

If you don't want any automation, pick Monitor only: we'll just notify you 30 / 14 / 7 days before expiry.

I have no SSH access

You don't need SSH for monitoring or for Let's Encrypt issuance. Typical workflow:

  • Monitor only — we watch expiry and alert you 30 / 14 / 7 days out.
  • Let's Encrypt tab — issue via DNS TXT on our servers, download the ZIP, install in cPanel, Plesk, Cloudflare, or your host's SSL UI. See Let's Encrypt via DNS.
  • Upload & deploy — only if you have a bastion or jump host with SSH to the destination; not required for DNS issuance.

Hosted platforms (Shopify, Wix, Squarespace) manage TLS for you — use monitor-only alerts or their built-in cert tools. See cPanel, Plesk & hosted platforms.

cPanel, Plesk & hosted platforms

ManageMyCert detects many control panels and CMS stacks when you add a domain. For shared hosting where you don't have root SSH:

  • cPanel — issue on the Let's Encrypt tab, download ZIP, then SSL/TLS → Manage SSL sites (or AutoSSL alternatives) and paste/upload cert.pem, privkey.pem, and chain as your panel requires.
  • Cloudflare — connect an API token to upload a custom edge certificate (Business/Enterprise or ACM). See Hosting panel install.
  • cPanel / Plesk — connect API credentials or upload the ZIP in SSL/TLS.
  • WordPress on VPS — download ZIP and point Nginx/Apache at fullchain.pem + privkey.pem, or enable optional SSH deploy.
  • Shopify / Wix / Squarespace — vendor-managed TLS; monitoring only. Do not expect SSH deploy to apply.

Direct API integration with cPanel, Plesk, and Cloudflare is available in the portal under Install certificate. WordPress and other CMS stacks use ZIP download until a supported API is added.

Logs & notifications

Every renewal run — manual button or scheduled worker — emits a step-by-step trail you can read from the following places:

  • Activity log tab on the domain page (per-step events with severity, target, files written, commands run, error).
  • Audit logs page for the workspace (exportable as CSV/PDF).

After every renewal — success or failure — ManageMyCert sends a notification:

  • Through the channels enabled for that domain — your SMTP / SMS / Slack gateways when configured.
  • For email, if you have not added an SMTP gateway, workspace admins receive platform email.
  • SMS and Slack are only sent when you have configured those gateways (bring your own).

The message includes the host, status, deploy target list, file count, command count, and (on failure) the precise error with hints — e.g. "mkdir denied, enable Use sudo for cert install" or "Let's Encrypt could not reach port 80".

Troubleshooting

Renewal hangs and times out after several minutes.
Open the Activity log for the last step before the timeout — usually one of:

  • SFTP open never returns: account is SFTP-only; switch the cert directory to a writable path or use sudo install.
  • local probe failed: ETIMEDOUT … :80: port 80 not reachable. See "Let's Encrypt cannot validate" below.
  • waitForValidStatus: Let's Encrypt couldn't fetch the token from the public internet.

"mkdir: cannot create directory … Permission denied" while installing the cert.
The SSH user can't write under /etc/... or /usr/local/etc/.... Enable Use sudo for cert install (root-owned directories) on the deploy form (or per target) and add a sudoers entry — see Installing into root-owned directories.

Renewal hangs on mkdir -p for the webroot.
Some accounts have ForceCommand internal-sftp set in sshd_config — remote exec hangs. ManageMyCert now creates the webroot with SFTP mkdir only, but the SSH user must still be allowed to create files there. Either change ownership of the webroot, or use a directory under the deploy user's home as the webroot (Nginx/Apache alias snippet above).

"HTTP 301" or "HTTP 302" fetching /.well-known/acme-challenge/.
Your web server is redirecting all HTTP traffic to HTTPS. Let's Encrypt needs the challenge file on plain HTTP port 80 with status 200. Exclude /.well-known/acme-challenge/ from the redirect in Apache or Nginx — full examples in HTTP→HTTPS redirect blocks renewal. Quick test: curl -I http://your-domain/.well-known/acme-challenge/ping must not return 301.

Let's Encrypt cannot validate ETIMEDOUT … :80.
Timeouts (vs. ECONNREFUSED) almost always mean a firewall is silently dropping packets. Check:

sudo ss -tlnp | grep ':80 '
sudo iptables -L -n -v
sudo nft list ruleset 2>/dev/null
sudo ufw status 2>/dev/null
sudo firewall-cmd --list-all 2>/dev/null

From a third-party host: nc -vz your-domain.com 80 and curl -v http://your-domain.com/ -m 8. Open inbound TCP 80 in the cloud security group and the OS firewall, confirm public DNS, then retry.

"sudo: a password is required" or "sudo: no tty present".
Add NOPASSWD to the sudoers entry and Defaults:<user> !requiretty for that user. Test from the SSH user's shell on the server: sudo -n sh -c 'echo ok' should print ok with no prompt.

"Failed to restart X: Interactive authentication required."
Polkit / systemd is rejecting the call because the reload command is running as the SSH user, not root. Two fixes together: (1) prefix the reload command in the portal with sudo -n, and (2) allow that exact command in sudoers — see Reload/restart sudoers. So instead of systemctl restart opensips use sudo -n systemctl restart opensips in the portal, and add mmc-deploy ALL=(root) NOPASSWD: /bin/systemctl restart opensips on the server.

"ACME_EMAIL must be a real contact mailbox".
Set ACME_EMAIL in .env to a mailbox you own. Let's Encrypt rejects any address ending in example.com / example.net / example.org.

"DNS TXT not found yet for _acme-challenge…".
The ACME TXT record hasn't propagated. Confirm host/name and value match the portal exactly (no extra quotes in the DNS UI if it adds them automatically). Check with dig TXT _acme-challenge.example.com +short or an online DNS checker, then click Issue certificate again.

"A valid certificate is already on file… new issuance is available when 30 days or less remain."
Download the existing cert from the Let's Encrypt tab. Re-issue only when you're inside the renewal window — see 30-day issuance window.

Teams & members

Each account gets a workspace (organization). Admins can invite teammates by email from Team; invitees must create an account first. Members can view domains and alerts; admins manage billing, audit logs, and invites.

Balance & billing

Metered automation uses a prepaid USD balance. Workspace admins add funds in Settings → Billing. Auto deploy (hosting API install, SSH push, auto renew) requires at least $3.00 USD workspace balance; monitoring and Let's Encrypt ZIP download stay free. Auto top-up charges your saved card when balance falls to or below a threshold — you must complete at least one manual top-up first so a card is on file.

Admins receive platform email for manual top-ups, successful auto top-ups, failed auto top-ups, and low balance. When balance needs attention, workspace admins also receive the low-balance notice sent through the platform SMTP settings on the server

Audit and compliance exports: GET /api/logs (paginated, optional start, end, domain_id), and admin-only GET /api/logs/export.csv / export.pdf with the same filters.

FAQ

Is it really free?
Monitoring, alerting, and most features are free. Some heavy automation is billed against a small prepaid balance (see Billing in the portal).

Do you store my private keys?
Only if you explicitly enable auto-deploy. They're AES-256-GCM encrypted with a key that's distinct from your account password.

What if I just want monitoring?
Skip SSH and the Let's Encrypt tab. Add a domain, verify ownership, set alerts — done.

Do I need to give you an SSH key for Let's Encrypt?
No. Use the Let's Encrypt tab (DNS-01). We issue on our servers; you download a ZIP and install it yourself. SSH is optional for push-only deploy. See Let's Encrypt via DNS.

Why can't I issue a new certificate yet?
If a valid cert is already stored with more than 30 days left, download it instead of re-issuing. See 30-day issuance window.

I have 2 servers and need the same cert on both — what do I configure?
Generate one keypair on your laptop. Install the public key into authorized_keys on each server. In the portal, set the primary deploy fields to Server A, then click Add server for Server B. Each target has its own paths/reloads. The same cert is pushed to every target after one issuance. See Walkthrough: 2 servers, same certificate.

Is pasting just the private key enough to connect?
No. The portal also needs host, port (default 22), username, and at least one cert directory. For Auto-renew it also needs either a webroot or the standalone listener enabled. The private key alone gets us authenticated, not configured.

My target has no web server (XMPP, mail, App, Asterisk, OpenSIPS, VPN…). How do I auto-renew?
Enable Use standalone HTTP listener on the deploy form. ManageMyCert spins a tiny HTTP server on the target via SSH for the few seconds Let's Encrypt needs, then stops it. See HTTP-01 standalone.

Cert directory is owned by root. Now what?
Enable Use sudo for cert install (root-owned directories), optionally set owner:group. We stage files in the SSH user's home, then run a single sudo -n sh -c "mkdir -p; cp -f; chmod". See Installing into root-owned directories.

Where do I see what each step did?
The domain's Activity log tab and the workspace Audit logs page list every step. See Logs & notifications.

Will I be notified when an auto-renew fails at 3 a.m.?
Yes. Every renewal — success or failure — fires a notification via the channels you selected on the domain (email / SMS / Slack / MS Teams etc...), using your own gateways. If none are set, workspace admins get a platform email.