import { useEffect, useState } from 'react' import Modal from 'react-bootstrap/Modal' import { apiRequest } from '../api/client' import { PageHeader, AdminButton, AdminAlert } from '../components/admin' interface Domain { id: number name: string port: string site_id: number site_name: string site_path: string } interface Certificate { name: string path: string } interface SslDiagnostics { vhost_dir: string include_snippet: string vhosts: { file: string; has_listen_80: boolean; has_listen_443: boolean; has_ssl_directives: boolean }[] any_vhost_listen_ssl: boolean nginx_effective_listen_443: boolean panel_vhost_path_in_nginx_t: boolean nginx_t_probe_errors: string[] /** Something accepted TCP when connecting to 127.0.0.1:443 from the panel process */ localhost_443_accepts_tcp: boolean /** ss/netstat reported :443 in listen table, or null if probe unavailable */ ss_reports_443_listen: boolean | null hints: string[] } export function DomainsPage() { const [domains, setDomains] = useState([]) const [certificates, setCertificates] = useState([]) const [diag, setDiag] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [requesting, setRequesting] = useState(null) const [requestDomain, setRequestDomain] = useState(null) const [requestEmail, setRequestEmail] = useState('') const load = () => { setLoading(true) Promise.all([ apiRequest('/ssl/domains'), apiRequest<{ certificates: Certificate[] }>('/ssl/certificates'), apiRequest('/ssl/diagnostics').catch(() => null), ]) .then(([d, c, di]) => { setDomains(d) setCertificates(c.certificates || []) setDiag(di) }) .catch((err) => setError(err.message)) .finally(() => setLoading(false)) } useEffect(() => { load() }, []) const handleRequestCert = (e: React.FormEvent) => { e.preventDefault() if (!requestDomain) return setRequesting(requestDomain.name) apiRequest<{ status: boolean }>('/ssl/request', { method: 'POST', body: JSON.stringify({ domain: requestDomain.name, webroot: requestDomain.site_path, email: requestEmail, }), }) .then(() => { setRequestDomain(null) load() }) .catch((err) => setError(err.message)) .finally(() => setRequesting(null)) } const hasCert = (domain: string) => certificates.some((c) => c.name === domain || c.name.startsWith(domain + ' ')) if (loading) { return ( <>

Loading…

) } return ( <> {error ? {error} : null}
Request Let's Encrypt certificates for your site domains. Requires certbot and nginx configured for the domain.
{diag ? (
HTTPS / nginx check
{diag.hints.length ? (
    {diag.hints.map((h, i) => (
  • {h}
  • ))}
) : null}
Include YakPanel vhosts inside the http block of the nginx process that serves your sites:
{diag.include_snippet}
Port 443 on this machine
  • Localhost TCP (127.0.0.1:443):{' '} {diag.localhost_443_accepts_tcp ? ( accepting connections ) : ( refused / nothing listening )}
  • Kernel listen table (ss):{' '} {diag.ss_reports_443_listen === null ? ( not checked ) : diag.ss_reports_443_listen ? ( 443 in LISTEN ) : ( no 443 in LISTEN )}

The panel cannot see your cloud provider firewall. If localhost shows open but browsers off-network fail, open TCP 443 in the VPS control panel (security group) and OS firewall.

{diag.vhosts.length > 0 ? (
Panel configs scanned:{' '} {diag.vhosts.map((v) => `${v.file}${v.has_listen_443 && v.has_ssl_directives ? ' (HTTPS block)' : ''}`).join(', ')}
) : null} {diag.nginx_t_probe_errors.length > 0 ? (
nginx -T probe: {diag.nginx_t_probe_errors.join(' | ')}
) : null}
) : null}
Domains (from sites)
{domains.length === 0 ? (
No domains. Add a site first.
) : ( domains.map((d) => (
{d.name} {d.port !== '80' ? :{d.port} : null} ({d.site_name})
{hasCert(d.name) ? ( Cert ) : ( { setRequestDomain(d) setRequestEmail('') }} > {requesting === d.name ? ( ) : ( 'Request SSL' )} )}
)) )}
Certificates
{certificates.length === 0 ? (
No certificates yet
) : ( certificates.map((c) => (
{c.name}
)) )}
setRequestDomain(null)} centered> Request SSL for {requestDomain?.name} {requestDomain ? (
setRequestEmail(e.target.value)} placeholder="admin@example.com" className="form-control" required />
setRequestDomain(null)}> Cancel {requesting ? 'Requesting…' : 'Request'}
) : null}
) }