{ "app": { "title": "EdgeGuard", "subtitle": "Native reverse-proxy / VPN / firewall" }, "nav": { "dashboard": "Dashboard", "domains": "Domains", "backends": "Backends", "routing": "Routing", "networks": "Network interfaces", "ipAddresses": "IP addresses", "ssl": "SSL certificates", "vpn": "VPN", "wireguard": "WireGuard", "forwardProxy": "Forward proxy", "dns": "DNS", "ntp": "Time (NTP)", "firewall": "Firewall", "cluster": "Cluster", "license": "License", "settings": "Settings", "section": { "overview": "Overview", "routing": "Routing", "network": "Network", "security": "Security", "system": "System" } }, "fw": { "title": "Firewall", "intro": "Fortigate-style: rules built from zones × address objects/groups × services/service groups × action. NAT is separate. Top-down, first-match.", "tabs": { "rules": "Rules", "nat": "NAT", "zones": "Zones", "addrObj": "Address objects", "addrGrp": "Address groups", "services": "Services", "svcGrp": "Service groups" }, "zone": { "name": "Name", "description": "Description", "builtin": "built-in", "builtinHint": "Built-in zones cannot be deleted — the renderer and anti-lockout rules depend on them.", "builtinNameLocked": "Name is built-in — cannot be changed because existing rules and interfaces reference it.", "namePattern": "Lowercase letters, digits, _ and -; must start with a letter, up to 32 chars.", "add": "Add zone", "edit": "Edit zone", "deleteConfirm": "Really delete zone {{name}}?" }, "ao": { "name": "Name", "kind": "Kind", "value": "Value", "description": "Description", "add": "Add address object", "edit": "Edit address object", "deleteConfirm": "Really delete address object {{name}}?" }, "ag": { "name": "Name", "members": "Members", "description": "Description", "add": "Add address group", "edit": "Edit address group", "selectMembers": "Select address objects", "deleteConfirm": "Really delete address group {{name}}?" }, "svc": { "name": "Name", "proto": "Protocol", "ports": "Ports", "portStart": "Port (start)", "portEnd": "Port (end)", "description": "Description", "builtinHint": "Built-in — not editable", "add": "Add service", "edit": "Edit service", "deleteConfirm": "Really delete service {{name}}?" }, "sg": { "name": "Name", "members": "Members", "description": "Description", "add": "Add service group", "edit": "Edit service group", "selectMembers": "Select services", "deleteConfirm": "Really delete service group {{name}}?" }, "rule": { "name": "Name", "priority": "Priority", "enabled": "Enabled", "log": "Log", "action": "Action", "src": "Source", "dst": "Destination", "service": "Service", "srcZone": "Source zone", "dstZone": "Dest. zone", "srcKind": "Source kind", "dstKind": "Dest. kind", "object": "Address object", "group": "Address group", "serviceKind": "Service kind", "serviceGroup": "Service group", "comment": "Comment", "add": "Add rule", "edit": "Edit rule", "deleteConfirm": "Really delete this rule?" }, "nat": { "name": "Name", "priority": "Priority", "kind": "Kind", "enabled": "Enabled", "match": "Match", "target": "Target", "inZone": "Ingress zone", "outZone": "Egress zone", "proto": "Protocol", "matchSrcCidr": "Source CIDR (match)", "matchDstCidr": "Dest. CIDR (match)", "matchDstCidrHint": "empty = any dest IP (e.g. box's public IP)", "dportStart": "Port (start)", "dportEnd": "Port (end)", "targetAddr": "Target address", "targetPortStart": "Target port (start)", "targetPortEnd": "Target port (end)", "comment": "Comment", "add": "Add NAT rule", "edit": "Edit NAT rule", "deleteConfirm": "Really delete this NAT rule?" }, "sys": { "title": "System rules (always active)", "chain": "Chain", "match": "Match", "action": "Action", "note": "Note", "policy": "Default policy", "policyValue": "Input DROP — everything must be explicitly allowed.", "order": "Evaluation", "orderValue": "System rules first, then operator rules top-down (priority asc, first-match).", "lockout": "Anti-lockout", "lockoutValue": "SSH (22) and the management UI (443) are always reachable — even the operator can't accidentally lock themselves out." } }, "networks": { "title": "Network interfaces", "intro": "Manage WAN, LAN, VLAN and bond interfaces. Read-only kernel discovery above; declared configuration below — runtime apply via systemd-networkd lands in a later release.", "systemDiscovered": "System interfaces (read-only)", "addInterface": "Add interface", "editInterface": "Edit interface", "name": "Name", "type": "Type", "parent": "Parent interface", "selectParent": "Select parent", "vlan": "VLAN", "vlanId": "VLAN ID", "composition": "Composition", "members": "Member interfaces", "selectMembers": "Select physical interfaces", "membersRequired": "At least one member interface is required", "membersHintBridge": "A bridge joins multiple physical ports at L2 — typically two ports for a software switch.", "membersHintBond": "A bond aggregates multiple physical ports into one logical link (LACP / active-backup).", "role": "Zone", "roleHint": "Zones are managed in Firewall → Zones. Custom zones (e.g. iot, guest) can be added there.", "mtu": "MTU", "active": "Active", "description": "Description", "actions": "Actions", "deleteConfirm": "Really delete interface {{name}}?" }, "ips": { "title": "IP addresses", "intro": "Addresses the kernel currently has (read-only above) plus addresses EdgeGuard additionally manages — including VIPs that follow the active cluster node on failover.", "systemDiscovered": "Kernel addresses (read-only)", "managedTitle": "Managed addresses", "family": "Family", "addAddress": "Add address", "editAddress": "Edit address", "interface": "Interface", "selectInterface": "Select interface", "address": "Address", "prefix": "Prefix", "vip": "VIP", "vipFlag": "Mark as VIP", "vipPriority": "VIP priority (cluster failover)", "active": "Active", "description": "Description", "actions": "Actions", "deleteConfirm": "Really delete address {{addr}}?" }, "auth": { "loginTitle": "Sign in", "email": "Email", "password": "Password", "login": "Sign in", "logout": "Sign out", "loginFailed": "Sign-in failed", "loggedInAs": "Signed in as" }, "setup": { "title": "First-time setup", "intro": "Create the admin account, declare the public FQDN, and — optionally — paste a license key. Without one, a 30-day trial starts.", "adminEmail": "Admin email", "adminPassword": "Admin password", "passwordRule": "At least 12 characters.", "fqdn": "Public FQDN", "acmeEmail": "ACME / Let's Encrypt email", "licenseKey": "License key (optional)", "submit": "Finish setup", "successTitle": "Setup complete", "successHint": "Redirecting you to sign-in." }, "dashboard": { "title": "Dashboard", "welcomeHint": "Overview of all running EdgeGuard components." }, "domains": { "title": "Domains", "intro": "Manage FQDNs that HAProxy terminates. Optional primary backend as catch-all; path-based routing via routing rules.", "addDomain": "Add domain", "editDomain": "Edit domain", "name": "Name", "active": "Active", "primaryBackend": "Primary backend", "primaryBackendHint": "Catch-all backend for requests with no matching routing rule. Optional — leave empty if all traffic is routed via routing rules.", "selectBackend": "Select backend", "noBackend": "no backend", "httpToHttps": "HTTP→HTTPS", "hsts": "HSTS", "notes": "Notes", "actions": "Actions", "edit": "Edit", "delete": "Delete", "deleteConfirm": "Really delete domain {{name}}?" }, "backends": { "title": "Backends", "intro": "Upstream pools (one backend = N servers). HAProxy balances load by the chosen algorithm; health-check path enables HTTP probes every 5s per server.", "addBackend": "Add backend pool", "editBackend": "Edit backend pool", "name": "Name", "scheme": "Scheme", "target": "Target", "healthCheck": "Health check path", "active": "Active", "usedBy": "Used by", "noDomain": "no domain", "attachedDomains": "Domains", "attachedDomainsHint": "Domains that use this backend as their primary. Selecting domains here reconfigures them directly — same source of truth as the Domain modal's backend picker.", "selectDomains": "Select domains", "lbAlgo": "Load balancing", "lbAlgoHint": "roundrobin = evenly, leastconn = pick the server with fewest active connections, source = sticky per client-IP hash (for stateful apps without shared session).", "websocket": "WebSocket support", "websocketHint": "On: allow long-lived WebSocket / long-poll connections (Proxmox console, SSH-over-WS, AsyncAPI) — tunnel idle 1h instead of 60s. Off: strict HTTP timeouts.", "servers": "Servers", "noServers": "no server", "nServers": "{{n}} servers", "serversIn": "Servers in “{{name}}”", "serverHintCreate": "Saving creates the pool only. Add servers in the next step — open the pool and click “Add server”.", "actions": "Actions", "deleteConfirm": "Really delete backend pool {{name}}? All servers in the pool will be removed too.", "server": { "intro": "Upstream servers in this pool. Order doesn't matter — the LB algorithm decides.", "add": "Add server", "edit": "Edit server", "name": "Server name", "address": "Address", "port": "Port", "target": "Endpoint", "weight": "Weight", "weightHint": "0–256. Higher = more traffic. 100 = default.", "backup": "Backup", "backupHint": "Backup servers receive traffic only when every primary (non-backup) server is down.", "empty": "No servers in the pool yet. Click “Add server” to get started.", "deleteConfirm": "Really delete server {{name}}?" } }, "routing": { "title": "Routing rules", "intro": "Path-prefix → backend mapping per domain. Lowest priority wins; catch-all via domain.primary_backend.", "addRule": "Add rule", "editRule": "Edit rule", "domain": "Domain", "pathPrefix": "Path prefix", "backend": "Backend", "priority": "Priority", "active": "Active", "actions": "Actions", "selectDomain": "Select domain", "selectBackend": "Select backend", "deleteConfirm": "Really delete this routing rule?" }, "cluster": { "title": "Cluster", "intro": "{{count}} node(s) registered. Multi-node cluster (KeyDB Active-Active + PG streaming replication) coming in a later release.", "id": "Node ID", "fqdn": "FQDN", "role": "Role", "joinedAt": "Joined", "self": "this node" }, "ssl": { "title": "SSL certificates", "intro": "Manage TLS certs — let EdgeGuard issue them via Let's Encrypt or upload your own PEM. HAProxy reloads automatically after each change.", "tabLE": "Let's Encrypt", "tabUpload": "Custom certificate", "leIntro": "Pick a domain, click Issue — EdgeGuard solves HTTP-01 over the ACME webroot, writes the PEM into /etc/edgeguard/tls/, and reloads HAProxy.", "uploadIntro": "Upload your own certificate. Format: PEM-encoded. Cert + optional chain + private key. EdgeGuard validates cert/key match before writing.", "uploadHint": "Tip: for Let's Encrypt renewals don't upload here — use the LE tab.", "domain": "Domain", "selectDomain": "Pick or type a domain", "domainExtra": "Includes the management FQDN (from Setup), cluster nodes and operator domains. You can also type any other domain — as long as DNS resolves to this box.", "fqdnHintMgmt": "management FQDN", "fqdnHintCluster": "cluster · {{role}}", "issuer": "Issuer", "status": "Status", "expiresIn": "Expires in", "expiredAgo": "expired {{days}} days ago", "actions": "Actions", "issueButton": "Issue certificate", "uploadButton": "Upload", "issueSuccess": "Certificate issued + installed.", "uploadSuccess": "Certificate uploaded + installed.", "deleteConfirm": "Delete certificate for {{domain}}? HAProxy falls back to the default cert for this domain.", "installedTitle": "Installed certificates", "certPem": "Certificate (PEM)", "chainPem": "Chain (PEM, optional)", "keyPem": "Private key (PEM)" }, "settings": { "title": "Settings", "intro": "System information and setup status. Editable values come in a later release.", "systemInfo": "System", "version": "Version", "status": "Status", "setupInfo": "Setup", "adminEmail": "Admin email", "fqdn": "FQDN", "setupCompleted": "Setup completed" }, "update": { "available": "Update available: version {{version}}", "multiPackageHint": "{{count}} packages will be updated.", "applyNow": "Install now", "confirmTitle": "Install update now?", "confirmDesc": "Packages will be updated to version {{version}}. edgeguard-api + scheduler restart (~2-5 s), HAProxy/nft/WG/Squid/Unbound/Chrony stay running.", "checkNow": "Check for updates", "checkDone": "Update available", "noUpdate": "No new updates", "checkFailed": "Update check failed", "running": "Update in progress …", "waitHint": "Please wait — the page will reload automatically once the new version is live.", "success": "Updated to {{version}}.", "failed": "Update failed", "stepDownload": "Download packages", "stepInstall": "Install", "stepRestart": "Service restart", "stepVerify": "Verification" }, "wg": { "title": "WireGuard", "intro": "WireGuard VPN tunnels. Server mode = we listen for peers; client mode = we dial out to a fixed upstream. Private keys are encrypted at rest.", "tabs": { "servers": "Server tunnels", "clients": "Client tunnels" }, "serverIntro": "Server tunnels host a peer roster — typically employee devices or branch sites. Each peer can be downloaded as a wg-quick.conf or scanned as a QR code.", "clientIntro": "Client tunnels connect EdgeGuard to a remote WireGuard server (e.g. HQ datacenter). Allowed IPs control which traffic is routed through the tunnel.", "iface": { "name": "Name", "namePattern": "wg followed by lowercase letters/digits/-, max 15 chars", "nameExtra": "Suggested: wg0, wg1, wg-hq …", "address": "Address (CIDR)", "addressExtra": "Box's tunnel IP, e.g. 10.99.0.1/24 for a /24 pool", "listenPort": "Listen port", "publicKey": "Public key", "privateKey": "Private key (paste)", "privateKeyExtra": "Fill in only if not auto-generating — base64 32 bytes. Stored encrypted.", "peerEndpoint": "Peer endpoint", "peerPublicKey": "Peer public key", "peerPSK": "Pre-shared key (PSK)", "peerPSKExtra": "Optional extra layer", "allowedIPs": "Allowed IPs", "allowedIPsExtra": "What gets routed through the tunnel. Default = full tunnel.", "keepalive": "Persistent keepalive (sec)", "mtu": "MTU", "zone": "Firewall zone", "description": "Description", "addServer": "Add server tunnel", "editServer": "Edit server tunnel", "addClient": "Add client tunnel", "editClient": "Edit client tunnel", "upstream": "Upstream peer", "deleteConfirm": "Really delete tunnel {{name}}? wg-quick will be stopped.", "keys": "Keys", "generateExtra": "If on: server generates a fresh Curve25519 keypair on save.", "generateOn": "Server-generated", "generateOff": "Manual paste", "editKeyWarning": "Warning: new keys invalidate all existing peer configs. Only change if intentional." }, "peers": { "button": "Peers", "drawerTitle": "Peer roster" }, "peer": { "name": "Name", "publicKey": "Public key", "publicKeyExtra": "Generated by the peer device; only paste here if the peer already has a keypair.", "allowedIPs": "Allowed IPs", "allowedIPsExtra": "Which tunnel IPs this peer is allowed to use. Typically /32 = one IP.", "keepalive": "Keepalive (sec)", "keepaliveExtra": "0 = off. Recommended 25 behind NAT.", "lastHandshake": "Last handshake", "never": "never", "description": "Description", "add": "Add peer", "edit": "Edit peer", "deleteConfirm": "Really remove peer {{name}}?", "keys": "Keys", "generateExtra": "If on: server generates a keypair for this peer and can hand out the config / QR. If off: paste the peer's public key only — no config download.", "pskExtra": "If on: server generates a 32-byte PSK for this peer.", "pskOn": "Generate PSK", "pskOff": "no PSK", "downloadConf": "Download wg-quick.conf", "qrTitle": "WireGuard QR", "qrHint": "Scan with the WireGuard app (iOS/Android): \"Add tunnel\" → \"Scan QR code\". Replace the Endpoint placeholder in the downloaded conf before use.", "online": "Online", "offline": "Offline", "traffic": "Traffic" } }, "dashboard": { "title": "Dashboard", "welcomeHint": "EdgeGuard overview — health, counts, live status of the major services.", "kpi": { "domains": "Domains", "backends": "Backends", "ifaces": "Interfaces", "fwRules": "FW rules", "natRules": "NAT rules", "wg": "WG connections" }, "wgCard": { "title": "WireGuard", "empty": "No WG tunnel configured yet." }, "firewallCard": { "title": "Firewall", "zones": "Zones", "activeRules": "{{rules}} active rules · {{nat}} NAT" }, "sslCard": { "title": "SSL certificates", "total": "Managed certificates", "expiringSoon": "{{count}} expiring soon (< 30 days)", "allFresh": "All certs have > 30 days remaining." }, "clusterCard": { "title": "Cluster", "nodes": "Nodes" }, "routingCard": { "title": "Routing", "domains": "Domains", "backends": "Backends", "attached": "{{count}}/{{total}} domains have a primary backend" }, "systemCard": { "title": "System", "version": "Version", "api": "API", "ifaces": "Interfaces", "wg": "WireGuard" }, "servicesCard": { "title": "Service status (live, 10s)" }, "activityCard": { "title": "Recent activity (audit log)", "empty": "No activity yet — mutations are logged here." }, "haproxyCard": { "title": "HAProxy backends (live)", "empty": "No backend stats reachable (HAProxy down or admin.sock permission)." }, "resCard": { "load": "Load", "memory": "Memory", "disk": "Disk /", "free": "free", "conntrack": "Conntrack", "uptime": "Uptime" } }, "ntp": { "title": "Time server (Chrony)", "intro": "Chrony as time-sync daemon (NTP). Sources on top, listen/serve config on the settings tab. With 'serve_clients' on and LAN-IPs bound, the box itself becomes an NTP server for the LAN.", "tabs": { "pools": "Sources", "settings": "Settings" }, "pool": { "kind": "Type", "kindPool": "pool — DNS round-robin (multiple servers from A records)", "kindServer": "server — single host", "address": "Address / host", "addressExtra": "FQDN (for pool: 0.de.pool.ntp.org) or IP.", "iburst": "iburst", "prefer": "prefer", "minpoll": "min-poll", "maxpoll": "max-poll", "options": "Options", "description": "Description", "add": "Add source", "edit": "Edit source", "deleteConfirm": "Really delete NTP source {{addr}}?" }, "settings": { "intro": "Global chrony settings. Saves reload chrony automatically.", "serveClients": "Act as NTP server for clients", "serveClientsExtra": "If off: chrony acts as client only (port 0). If on + listen IP: binds UDP/123.", "listenAddresses": "Listen addresses", "listenAddressesPlaceholder": "Pick IPs (or type)", "listenAddressesExtra": "Which IPs chrony binds :123/UDP on. 127.0.0.1+::1 = local only; LAN IPs open for LAN clients (FW rule auto-generated).", "allowACL": "Allow ACL (CIDRs)", "allowACLExtra": "Who is allowed to ask for NTP time.", "makestepSecs": "makestep secs", "makestepSecsExtra": "Allow step (vs. slew) when offset > N seconds.", "makestepLimit": "makestep limit", "rtcsync": "Sync RTC with system time", "rtcsyncExtra": "Keep hardware clock in sync every 11 min — after reboot time is roughly correct.", "leapsectz": "Leap-sec TZ", "leapsectzExtra": "Optional, e.g. 'right/UTC' for leap-sec via tzdata." } }, "dns": { "title": "DNS (Unbound)", "intro": "Unbound resolver on :53. Local zones (authoritative from DNS records) and forward zones (stub-zone to remote resolvers). Default forwarders catch everything else.", "tabs": { "zones": "Zones", "settings": "Resolver settings" }, "zone": { "name": "Zone name", "nameExtra": "FQDN without leading/trailing dot — e.g. internal.netcell-it.de", "type": "Type", "typeLocal": "local — authoritative (records here)", "typeForward": "forward — stub-zone to remote resolver", "forwardTo": "Upstream resolvers", "forwardToExtra": "Comma-separated IP list — e.g. '10.0.0.53, 8.8.8.8'", "description": "Description", "records": "Records …", "add": "Add zone", "edit": "Edit zone", "deleteConfirm": "Really delete zone {{name}} and all its records?" }, "record": { "name": "Name", "nameExtra": "Relative to zone (e.g. 'mailcow') or FQDN with trailing dot.", "type": "Type", "value": "Value", "valueExtra": "RDATA in text form: A → IP, CNAME → FQDN, MX → 'priority host', TXT → 'string'.", "ttl": "TTL (sec)", "drawerTitle": "DNS records", "add": "Add record", "edit": "Edit record", "deleteConfirm": "Really delete record {{name}}?" }, "settings": { "intro": "Global resolver settings. Saves reload Unbound automatically.", "listenAddresses": "Listen addresses", "listenAddressesPlaceholder": "Pick IPs (or type)", "listenAddressesRequired": "At least one address required.", "listenAddressesExtra": "Multi-select from kernel-discovered IPs. 127.0.0.1 + ::1 = local only; LAN iface IPs (e.g. 10.10.20.3) open the resolver to LAN clients. You can also type custom IPs (Enter).", "listenPort": "Port", "upstreamForwards": "Default forwarders", "upstreamForwardsExtra": "Where everything not local goes. Default 1.1.1.1 + 9.9.9.9.", "accessACL": "Access ACL (CIDRs)", "accessACLExtra": "Who is allowed to use this resolver.", "dnssec": "DNSSEC validation", "qnameMin": "QName minimisation (privacy)", "cacheMin": "Cache min-TTL", "cacheMax": "Cache max-TTL" } }, "fwd": { "title": "Forward proxy (Squid)", "intro": "Squid-based forward proxy on :3128. ACLs are evaluated top-down by priority — first match wins. If no rule matches, the default permits only localnet (10/8, 172.16/12, 192.168/16).", "helpTitle": "ACL ordering tip", "helpBody": "Higher priority = evaluated first. Example: 'deny .badsite.com' (priority 200) before 'allow .com' (priority 100). Values can be lists (multiple lines), regex depending on acl_type.", "name": "Name", "nameExtra": "Squid-conformant identifier — lowercase + _, no spaces.", "aclType": "Type", "aclTypeExtra": "What Squid matches (source, domain, port, …).", "value": "Value", "valueExtra": "Format depends on type — IPs/CIDRs for src/dst, domain with leading dot for dstdomain (.example.com also matches sub.example.com), regex for *_regex types.", "action": "Action", "priority": "Priority", "priorityExtra": "Higher = evaluated first.", "comment": "Comment", "add": "Add ACL", "edit": "Edit ACL", "deleteConfirm": "Really delete ACL {{name}}?" }, "common": { "yes": "Yes", "no": "No", "save": "Save", "cancel": "Cancel", "loading": "Loading …", "error": "Error", "edit": "Edit", "delete": "Delete", "deleteConfirm": "Really delete?", "search": "Search …", "totalRows": "{{count}} rows", "active": "Active", "inactive": "Inactive", "noData": "No data", "actions": "Actions", "add": "Add", "download": "Download", "copy": "Copy", "copied": "Copied" }, "license": { "title": "License", "status": "Status", "product": "Product", "key": "License key", "noKey": "No key configured", "validUntil": "Valid until", "expired": "Expired", "daysLeft": "{{days}} days left", "lastVerifiedAt": "Last verified", "verifiedBy": "Verified by", "limits": "Limits", "unlimited": "Unlimited", "features": "Features", "reverify": "Re-verify", "reverified": "License re-verified successfully", "enterKey": "Enter key", "replaceKey": "Replace key", "enterKeyHint": "Paste your license key from the self-service portal at license.netcell-it.com.", "activate": "Activate", "saved": "License saved and verified", "savedButVerifyFailed": "Key saved but server-verify failed", "clearKey": "Remove key", "cleared": "License removed — system falls back to trial", "confirmClear": "Really remove the license key?", "confirmClearHint": "The system will fall back to trial-mode once the key is deleted.", "lastVerifyFailed": "Last server verify failed", "trialExpiring": "Trial expires in {{days}} day(s)", "trialExpiringHint": "Activate a license before the trial period ends." }, "licenseBanner": { "expired": "License expired or invalid.", "trialExpiring": "Trial expires in {{days}} day(s).", "verifyFailed": "License verification failed", "cta": "Activate now →", "openPage": "Open license page →" } }