mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-06-01 21:14:49 +00:00
complete i18n migration to /[locale]/ with EN+ES content
Full rewrite of the docs site under app/[locale]/ with next-intl in localePrefix:"always" mode. Every page now exists at both /en/<path> and /es/<path>; the root / shows a meta-refresh + JS redirect to /<defaultLocale>/ so GitHub Pages serves something on the apex URL. Highlights: - 107 doc pages migrated to file-per-page JSON namespaces under messages/en/ and messages/es/. Spanish content is fully translated (no copy-of-English placeholders). - New documentation for the Active Suppressions section in the Settings tab and the per-event Dismiss dropdown in the Health Monitor modal. - New screenshots: dismiss-duration-dropdown.png and an updated health-suppression-settings.png. - Pagefind integrated for client-side search; index is built on every CI deploy (not committed). - RSS feeds: per-locale at /<locale>/rss.xml plus root /rss.xml for backward compat. - Removed the dead app/[locale]/guides/[slug]/ route — every guide now has its own static page and no markdown source remains. - Fixed orphan link /guides/nvidia -> /guides/nvidia-manual in docs/hardware/nvidia-host. - Removed obsolete components (footer2, calendar, drawer). Verified locally with `npm ci && npm run build`: 2804 files in out/, 231 pages indexed by pagefind, root redirect intact, both locale roots and the new Active Suppressions docs render OK.
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Fail2Ban | ProxMenux Documentation",
|
||||
"description": "Install Fail2Ban with three jails tuned for Proxmox (SSH aggressive, Proxmox UI 8006, ProxMenux Monitor 8008). Includes the journald MaxLevelStore fix, custom log services for reliability, auto-detected nftables/iptables backend and SSH MaxAuthTries hardening.",
|
||||
"ogTitle": "Fail2Ban | ProxMenux Documentation",
|
||||
"ogDescription": "Brute-force protection for SSH and Proxmox web UIs, with Proxmox-specific journald and backend fixes."
|
||||
},
|
||||
"header": {
|
||||
"title": "Fail2Ban",
|
||||
"description": "Installs Fail2Ban with a Proxmox-specific configuration: three jails (SSH aggressive, Proxmox UI on port 8006, ProxMenux Monitor on port 8008 + reverse proxy), a journald log-level fix so SSH auth events are actually stored, two journal-to-file logger services that work around a known Fail2Ban systemd-backend issue, auto-detected firewall backend and SSH MaxAuthTries hardening.",
|
||||
"section": "Security"
|
||||
},
|
||||
"intro": {
|
||||
"title": "What this does",
|
||||
"body": "Installs Fail2Ban from the Debian repos and writes a complete Proxmox-tuned configuration that protects three attack surfaces (SSH, Proxmox UI, ProxMenux Monitor) out of the box. Detects an existing install and offers a manage menu (reinstall / remove) instead of re-running the installer."
|
||||
},
|
||||
"firstLaunch": {
|
||||
"heading": "First-launch dialog",
|
||||
"body": "On a host without Fail2Ban, the script shows a confirmation dialog summarising everything it's about to install and configure. Cancel exits without changes; confirm starts the install flow.",
|
||||
"imageAlt": "Fail2Ban install confirmation dialog listing the three jails, journald fix and SSH hardening"
|
||||
},
|
||||
"jails": {
|
||||
"heading": "The three jails",
|
||||
"headerJail": "Jail",
|
||||
"headerProtects": "Protects",
|
||||
"headerRetries": "Retries / Window",
|
||||
"headerBan": "Ban time",
|
||||
"rows": [
|
||||
{
|
||||
"jail": "[sshd]",
|
||||
"protects": "SSH (aggressive mode — covers ddos, mode, normal)",
|
||||
"retries": "2 / 60 min",
|
||||
"ban": "9 hours"
|
||||
},
|
||||
{
|
||||
"jail": "[proxmox]",
|
||||
"protects": "Proxmox web UI (port 8006)",
|
||||
"retries": "3 / 10 min",
|
||||
"ban": "1 hour"
|
||||
},
|
||||
{
|
||||
"jail": "[proxmenux]",
|
||||
"protects": "ProxMenux Monitor (port 8008 + http/https reverse proxy)",
|
||||
"retries": "3 / 10 min",
|
||||
"ban": "1 hour"
|
||||
}
|
||||
],
|
||||
"outro": "Global defaults from <code>jail.local</code>: <code>ignoreip = 127.0.0.1/8 ::1</code>, <code>ignoreself = true</code>,<code> bantime = 86400</code> (24h fallback for jails that don't override it), <code>maxretry = 2</code>, <code>findtime = 1800</code>."
|
||||
},
|
||||
"journald": {
|
||||
"heading": "Why the journald fix matters",
|
||||
"intro": "Proxmox ships <code>/etc/systemd/journald.conf</code> with <codeNw>MaxLevelStore=warning</codeNw>. journald drops every log message <em>below</em> warning before storing it. SSH and PAM emit auth failures at <em>info</em> / <em>notice</em> levels, so:",
|
||||
"diagram": {
|
||||
"sshLabel": "SSH / PAM",
|
||||
"sshDetail": "auth failure\n(info / notice level)",
|
||||
"journaldLabel": "journald",
|
||||
"journaldDetail": "MaxLevelStore=warning\n→ event silently dropped",
|
||||
"fail2banLabel": "Fail2Ban",
|
||||
"fail2banDetail": "sees nothing\n→ never bans anything",
|
||||
"arrowLabel": "default Proxmox"
|
||||
},
|
||||
"afterDiagram": "The installer detects this and writes a drop-in at <codeXs>/etc/systemd/journald.conf.d/proxmenux-loglevel.conf</codeXs> raising both <code>MaxLevelStore</code> and <code>MaxLevelSyslog</code> to <code>info</code>:",
|
||||
"code": "[Journal]\nMaxLevelStore=info\nMaxLevelSyslog=info",
|
||||
"outro": "Then restarts <code>systemd-journald</code>. The drop-in is removed on uninstall, restoring the original Proxmox default."
|
||||
},
|
||||
"loggers": {
|
||||
"heading": "Why two custom logger services",
|
||||
"intro1": "Fail2Ban can read directly from the systemd journal (<code>backend = systemd</code>), but on Proxmox this backend has known reliability issues with <code>pvedaemon</code> worker processes (auth events appear in the journal but Fail2Ban doesn't always pick them up) and intermittently with <code>sshd</code>.",
|
||||
"intro2": "The workaround: ProxMenux creates two tiny systemd services that <code>journalctl -f</code> the relevant units and append every line to a file. Fail2Ban then reads those files with the rock-solid <code>backend = auto</code> (file mode):",
|
||||
"headerService": "Service",
|
||||
"headerSource": "Source unit",
|
||||
"headerOutput": "Output file",
|
||||
"rows": [
|
||||
{
|
||||
"service": "proxmox-auth-logger.service",
|
||||
"source": "pvedaemon.service",
|
||||
"output": "/var/log/proxmox-auth.log"
|
||||
},
|
||||
{
|
||||
"service": "ssh-auth-logger.service",
|
||||
"source": "ssh.service",
|
||||
"output": "/var/log/ssh-auth.log"
|
||||
}
|
||||
],
|
||||
"outro": "Both services are declared <code>PartOf=fail2ban.service</code> so they restart with Fail2Ban and stop with it. Mode 640 owned by <code>root:adm</code> on the log files. The third log used by the <code>[proxmenux]</code> jail (<code>/var/log/proxmenux-auth.log</code>) is written directly by the ProxMenux Monitor Flask app — no logger service needed for that one."
|
||||
},
|
||||
"backend": {
|
||||
"heading": "Firewall backend auto-detection",
|
||||
"intro": "The installer probes the host: if <code>nft list ruleset</code> works, it picks <code>nftables</code> as the ban action. Otherwise it falls back to <code>iptables-multiport</code> / <code>iptables-allports</code>. The choice is written into <code>jail.local</code>:",
|
||||
"code": "# nftables host\nbanaction = nftables\nbanaction_allports = nftables[type=allports]\n\n# iptables host (fallback)\nbanaction = iptables-multiport\nbanaction_allports = iptables-allports"
|
||||
},
|
||||
"hardening": {
|
||||
"heading": "SSH hardening: MaxAuthTries",
|
||||
"intro": "Lynis control <strong>SSH-7408</strong> recommends <code>MaxAuthTries 3</code> in <code>sshd_config</code>. With Fail2Ban's <code>maxretry = 2</code> on the SSH jail, a malicious client never reaches three attempts anyway — but the explicit setting satisfies the audit and adds defence in depth (e.g. if Fail2Ban is stopped for maintenance).",
|
||||
"installerIntro": "The installer:",
|
||||
"items": [
|
||||
"Reads the current <code>MaxAuthTries</code> value (or defaults to 6 if absent).",
|
||||
"Saves it to <code>/usr/local/share/proxmenux/sshd_maxauthtries_backup</code>.",
|
||||
"Edits <code>sshd_config</code> in-place — replaces existing line, uncomments commented line, or appends.",
|
||||
"Reloads <code>sshd</code> (reload, not restart, to keep existing sessions alive)."
|
||||
],
|
||||
"outro": "On uninstall, the saved original value is restored and <code>sshd</code> is reloaded again."
|
||||
},
|
||||
"manage": {
|
||||
"heading": "Manage an existing install",
|
||||
"intro": "If Fail2Ban is already installed when you open the menu, the script detects it and shows a manage menu instead of re-running the installer:",
|
||||
"headerAction": "Action",
|
||||
"headerWhat": "What it does",
|
||||
"rows": [
|
||||
{
|
||||
"action": "Reinstall",
|
||||
"what": "Re-runs the full installer — rewrites all jails with the current ProxMenux defaults. Use this after a ProxMenux update bumps the recommended values."
|
||||
},
|
||||
{
|
||||
"action": "Remove",
|
||||
"what": "Stops fail2ban and the two logger services, purges the apt package, removes all jail / filter files, deletes the journald drop-in (restoring the Proxmox default), and restores the original SSH MaxAuthTries."
|
||||
}
|
||||
]
|
||||
},
|
||||
"verify": {
|
||||
"heading": "Verify it's working",
|
||||
"intro": "After installation, useful commands from the host:",
|
||||
"code": "# Service status and version\nsystemctl status fail2ban\nfail2ban-client --version\n\n# All active jails\nfail2ban-client status\n\n# Detail on one jail\nfail2ban-client status sshd\nfail2ban-client status proxmox\nfail2ban-client status proxmenux\n\n# Currently banned IPs in a jail\nfail2ban-client status sshd | grep \"Banned IP\"\n\n# Manually unban an IP (use this if you ban yourself)\nfail2ban-client unban 192.0.2.10\n\n# Tail the auth logs Fail2Ban watches\ntail -f /var/log/ssh-auth.log\ntail -f /var/log/proxmox-auth.log\ntail -f /var/log/fail2ban.log"
|
||||
},
|
||||
"troubleshoot": {
|
||||
"heading": "Troubleshooting",
|
||||
"neverBansTitle": "Fail2Ban runs but never bans anything",
|
||||
"neverBansBody": "Check the auth log files actually receive entries: <code>tail -f /var/log/ssh-auth.log</code> and try a wrong-password SSH attempt from a different machine. If the log stays empty, the logger service is not running: <code>systemctl status ssh-auth-logger.service</code>. If it's active but the log is empty, check that the journald drop-in took effect: <code>journalctl --dump-catalog | head</code> — events at <em>info</em> level should be visible.",
|
||||
"monitorEmptyTitle": "ProxMenux Monitor jail has no entries even after failed logins",
|
||||
"monitorEmptyBody": "The <code>[proxmenux]</code> jail reads <code>/var/log/proxmenux-auth.log</code>, which is written by the ProxMenux Monitor Flask app — not by a journald logger. If you don't run the Monitor, the file stays empty and the jail never fires. That's expected; the jail config is harmless. If you do run the Monitor and the log is empty, check the Flask logging config.",
|
||||
"selfBanTitle": "I banned myself",
|
||||
"selfBanIntro": "From a console / IPMI / iKVM (or another whitelisted IP):",
|
||||
"selfBanCode": "fail2ban-client unban '<'YOUR_IP'>'\n\n# To prevent it next time, edit /etc/fail2ban/jail.local and add your IP:\nignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 203.0.113.42\n\n# Then reload\nfail2ban-client reload",
|
||||
"aptFailTitle": "apt-get fails: ''Unable to locate package fail2ban''",
|
||||
"aptFailBody": "The host is missing the Debian repos (common on barebones Proxmox installs). The installer detects this and writes <code>/etc/apt/sources.list.d/debian.sources</code> with the right codename (<code>bookworm</code> / <code>trixie</code>) before retrying. If it still fails, check <code>/etc/os-release</code> for <code>VERSION_CODENAME</code> and confirm the repo URL is reachable.",
|
||||
"lockoutTitle": "SSH locks me out after install",
|
||||
"lockoutBody": "The installer sets <code>MaxAuthTries=3</code>. If your password manager / agent retries multiple keys, you may exceed that on a single connection attempt. Limit the keys offered: <code>ssh -o IdentitiesOnly=yes -i ~/.ssh/specific_key user@host</code>. Or temporarily raise <code>MaxAuthTries</code> in <code>sshd_config</code> while you debug."
|
||||
},
|
||||
"files": {
|
||||
"heading": "Files written",
|
||||
"code": "/etc/fail2ban/jail.local # global defaults + [sshd]\n/etc/fail2ban/jail.d/proxmox.conf # [proxmox]\n/etc/fail2ban/jail.d/proxmenux.conf # [proxmenux]\n/etc/fail2ban/filter.d/proxmox.conf # auth-failure regex for pvedaemon\n/etc/fail2ban/filter.d/proxmenux.conf # auth-failure regex for Monitor\n/etc/systemd/system/proxmox-auth-logger.service # journal → file (pvedaemon)\n/etc/systemd/system/ssh-auth-logger.service # journal → file (sshd)\n/etc/systemd/journald.conf.d/proxmenux-loglevel.conf # MaxLevelStore=info\n/etc/ssh/sshd_config # MaxAuthTries=3 (in-place edit)\n/var/log/proxmox-auth.log # written by logger service\n/var/log/ssh-auth.log # written by logger service\n/var/log/proxmenux-auth.log # written by Monitor Flask app\n/usr/local/share/proxmenux/sshd_maxauthtries_backup # for restore on uninstall"
|
||||
},
|
||||
"related": {
|
||||
"heading": "Related",
|
||||
"monitorLabel": "ProxMenux Monitor → Security tab",
|
||||
"monitorTail": " — same install reachable from the dashboard, plus live jail status, banned IPs and per-jail retry / ban-time tuning from the browser.",
|
||||
"lynisLabel": "Lynis",
|
||||
"lynisTail": " — run a security audit before/after to confirm the SSH-7408 control is satisfied.",
|
||||
"securityLabel": "Security overview",
|
||||
"securityTail": " — back to the section overview."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Proxmox Security — Fail2Ban, Lynis Hardening Audit | ProxMenux",
|
||||
"description": "Two installable security tools for Proxmox VE: Fail2Ban (intrusion prevention for SSH, the Proxmox web UI and the ProxMenux Monitor) and Lynis (security audit and hardening scanner installed from upstream GitHub).",
|
||||
"ogTitle": "Proxmox Security — Fail2Ban, Lynis Hardening Audit",
|
||||
"ogDescription": "Fail2Ban and Lynis for Proxmox VE — intrusion prevention plus a hardening audit installed and managed by ProxMenux.",
|
||||
"twitterTitle": "Proxmox Security | ProxMenux",
|
||||
"twitterDescription": "Fail2Ban and Lynis for Proxmox VE — intrusion prevention and hardening audit."
|
||||
},
|
||||
"header": {
|
||||
"title": "Security",
|
||||
"description": "Two complementary security tools for Proxmox VE: an active defence (Fail2Ban — bans IPs that attack SSH or the web UIs) and an offline audit (Lynis — scans the system for hardening gaps and gives a 0–100 score). Both are installed and managed through their own dedicated menu, with detection of an existing install before any action.",
|
||||
"section": "Security"
|
||||
},
|
||||
"intro": {
|
||||
"title": "Active defence vs. offline audit",
|
||||
"body": "These two tools answer different questions. <strong>Fail2Ban</strong> answers <em>\"is something attacking us right now?\"</em> by watching auth logs and banning offending IPs. <strong>Lynis</strong> answers <em>\"how hardened is this host?\"</em> by running a one-shot audit and printing concrete recommendations. Use both together: Lynis tells you what to fix, Fail2Ban handles the live abuse."
|
||||
},
|
||||
"opening": {
|
||||
"heading": "Opening the menu",
|
||||
"body": "From ProxMenux's main menu, select <strong>Security</strong>. You will see this:",
|
||||
"imageAlt": "Security menu with Fail2Ban and Lynis options"
|
||||
},
|
||||
"pick": {
|
||||
"heading": "Pick your tool",
|
||||
"body": "The two security tools are independent — install either one, both, or neither. Each card below jumps to the section that explains the tool in detail."
|
||||
},
|
||||
"cards": {
|
||||
"fail2ban": {
|
||||
"title": "Fail2Ban",
|
||||
"body": "Active intrusion prevention. Watches SSH and web UI auth logs and bans IPs after repeated failures.",
|
||||
"bullets": [
|
||||
"Three jails: SSH, Proxmox UI (8006), ProxMenux Monitor (8008)",
|
||||
"Fixes Proxmox journald defaults that block auth logs",
|
||||
"Auto-detects nftables / iptables",
|
||||
"SSH hardening: MaxAuthTries=3 (Lynis recommendation)"
|
||||
]
|
||||
},
|
||||
"lynis": {
|
||||
"title": "Lynis",
|
||||
"body": "Offline security auditor. Scans the host and prints a hardening score plus concrete remediation hints.",
|
||||
"bullets": [
|
||||
"Installed from upstream CISOfy GitHub (always latest)",
|
||||
"Hardening score 0–100 + list of warnings and suggestions",
|
||||
"Run-audit and update actions in-menu",
|
||||
"Read-only by design — never changes the system"
|
||||
]
|
||||
}
|
||||
},
|
||||
"workflowTip": {
|
||||
"title": "Workflow that uses both",
|
||||
"body": "Run a Lynis audit first to see your starting score and the top recommendations. Apply the fixes you want. Then install Fail2Ban — it implements one of Lynis's most common recommendations (SSH brute-force protection) automatically, and adjusts <code>MaxAuthTries</code> in <code>sshd_config</code> to satisfy the SSH-7408 control. Re-run Lynis afterwards to confirm the score improved."
|
||||
},
|
||||
"fail2banSection": {
|
||||
"heading": "Fail2Ban",
|
||||
"body": "ProxMenux installs Fail2Ban with a configuration tuned for Proxmox specifically. Beyond the standard SSH jail, it adds protection for the Proxmox web UI and the ProxMenux Monitor, and works around two Proxmox-specific quirks: a journald default that drops auth events, and the systemd-backend issue that prevents Fail2Ban from reading certain journal sources reliably. The detail page covers the full install flow, the three jails, the journald fix, the SSH hardening change and the troubleshooting cheatsheet.",
|
||||
"optionTitle": "Fail2Ban — install & manage",
|
||||
"optionDescription": "Three pre-configured jails (sshd aggressive, Proxmox UI port 8006, ProxMenux Monitor port 8008 + reverse proxy), auto-detected nftables/iptables backend, journald fix and SSH MaxAuthTries hardening."
|
||||
},
|
||||
"lynisSection": {
|
||||
"heading": "Lynis",
|
||||
"body": "ProxMenux clones Lynis from <code>github.com/CISOfy/lynis</code> into <code>/opt/lynis</code> and exposes it as <code>/usr/local/bin/lynis</code>. The Debian package is intentionally avoided because it lags several major versions behind upstream. The detail page covers the install / audit / update / uninstall flow, how to read the report, and how to act on the findings.",
|
||||
"optionTitle": "Lynis — install, audit & manage",
|
||||
"optionDescription": "Installs the latest Lynis from the official CISOfy GitHub repo (not the older Debian package), runs system audits with hardening score, and updates via git pull."
|
||||
},
|
||||
"componentStatus": {
|
||||
"heading": "Component status",
|
||||
"body": "Both installers register their state in <code>/usr/local/share/proxmenux/components_status.json</code> under the <code>security</code> category. ProxMenux uses this file to decide whether to show the install or the manage menu on subsequent runs, and the same data feeds the dashboards in the ProxMenux Monitor when present."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Lynis | ProxMenux Documentation",
|
||||
"description": "Install Lynis from the official CISOfy GitHub repository (always latest), run a system audit with hardening score 0–100, update via git pull. Read-only by design — never modifies the system.",
|
||||
"ogTitle": "Lynis | ProxMenux Documentation",
|
||||
"ogDescription": "Install and run the Lynis security auditor on Proxmox VE. Upstream GitHub install, audit, update."
|
||||
},
|
||||
"header": {
|
||||
"title": "Lynis",
|
||||
"description": "Clones the latest Lynis from the official CISOfy GitHub repository, exposes it as /usr/local/bin/lynis and offers run-audit / update / reinstall / uninstall actions from the menu. Read-only auditor by design — never modifies the system, only reports.",
|
||||
"section": "Security"
|
||||
},
|
||||
"intro": {
|
||||
"title": "What this does",
|
||||
"body": "Installs Lynis (the open-source security auditor by CISOfy) from upstream GitHub into <code>/opt/lynis</code> and creates a wrapper at <code>/usr/local/bin/lynis</code> so it's in your <code>PATH</code>. Detects an existing install on launch and shows a manage menu (audit / update / reinstall / remove) instead."
|
||||
},
|
||||
"manageMenu": {
|
||||
"heading": "Manage menu (after install)",
|
||||
"intro": "Once Lynis is installed, every subsequent invocation opens the management menu instead of re-running the installer. From here you launch an audit, update via git pull, reinstall or uninstall:",
|
||||
"imageAlt": "Lynis management menu with audit, update, reinstall and remove options"
|
||||
},
|
||||
"whyUpstream": {
|
||||
"heading": "Why upstream GitHub, not apt",
|
||||
"intro": "Debian ships Lynis through apt, but the package typically lags several major versions behind upstream. Newer controls, fixes for new attack vectors and refined recommendations only land in the GitHub repo. Lynis itself is a self-contained shell script — no compilation, no dependencies beyond <code>git</code> for the install — so cloning the repo is the canonical install method recommended by CISOfy themselves.",
|
||||
"headerSource": "Source",
|
||||
"headerPath": "Install path",
|
||||
"headerUpdate": "Update method",
|
||||
"headerFresh": "Version freshness",
|
||||
"rows": [
|
||||
{
|
||||
"sourceRich": "<strong>ProxMenux (this script)</strong>",
|
||||
"path": "/opt/lynis/",
|
||||
"update": "git pull (in-menu)",
|
||||
"fresh": "Latest upstream"
|
||||
},
|
||||
{
|
||||
"sourceRich": "<strong>Debian apt</strong>",
|
||||
"path": "/usr/bin/lynis",
|
||||
"update": "apt upgrade",
|
||||
"fresh": "Often months / years behind"
|
||||
}
|
||||
]
|
||||
},
|
||||
"install": {
|
||||
"heading": "How the install works",
|
||||
"node1Label": "github.com/CISOfy/lynis",
|
||||
"node1Detail": "git clone\n(install git first if missing)",
|
||||
"node2Label": "/opt/lynis/",
|
||||
"node2Detail": "full repo\nincluding ./lynis script",
|
||||
"node3Label": "/usr/local/bin/lynis",
|
||||
"node3Detail": "wrapper:\ncd /opt/lynis && ./lynis $@",
|
||||
"outro": "The wrapper is mandatory — Lynis insists on being run from its own directory because it loads relative paths for plugins and profile data. The wrapper hides that detail so <code>lynis audit system</code> just works from anywhere."
|
||||
},
|
||||
"detection": {
|
||||
"heading": "Detection paths",
|
||||
"intro": "Before showing the menu, the script checks three locations to decide if Lynis is already present:",
|
||||
"items": [
|
||||
"<code>/usr/local/bin/lynis</code> — wrapper installed by ProxMenux",
|
||||
"<code>/opt/lynis/lynis</code> — direct path (in case the wrapper got removed)",
|
||||
"<code>/usr/bin/lynis</code> — apt-installed version, if the user installed it that way previously"
|
||||
],
|
||||
"outro": "If any of these is found, the manage menu opens. The script <strong>does not</strong> uninstall an apt-installed Lynis — only the one it manages itself (<code>/opt/lynis</code> + the wrapper)."
|
||||
},
|
||||
"audit": {
|
||||
"heading": "Run an audit",
|
||||
"intro": "From the manage menu, choose <strong>Run security audit now</strong>. This is equivalent to executing:",
|
||||
"code": "lynis audit system --no-colors",
|
||||
"outro": "The audit takes 30 seconds to a few minutes depending on host size. Output streams directly to the terminal — there is no spinner. Lynis prints sections for each control category, marking each test as <ok>[ OK ]</ok>, <warn>[ WARNING ]</warn> or <sugg>[ SUGGESTION ]</sugg>. The summary at the end has the headline numbers:",
|
||||
"summary": "================================================================================\n\n Lynis security scan details:\n\n Hardening index : 76 [############ ]\n Tests performed : 247\n Plugins enabled : 0\n\n Components:\n - Firewall [V]\n - Malware scanner [X]\n\n Lynis modules:\n - Compliance status [?]\n - Security audit [V]\n - Vulnerability scan [V]\n\n================================================================================"
|
||||
},
|
||||
"report": {
|
||||
"heading": "Reading the report",
|
||||
"intro": "The two important sections are <strong>Warnings</strong> (things you should fix soon) and <strong>Suggestions</strong> (recommendations to improve hardening). Each item carries a control ID like <code>SSH-7408</code> — useful when searching the Lynis docs for the rationale and the fix.",
|
||||
"headerMarker": "Marker",
|
||||
"headerMeaning": "Meaning",
|
||||
"headerAction": "Action",
|
||||
"rows": [
|
||||
{
|
||||
"markerRich": "<strong>OK</strong>",
|
||||
"meaning": "Test passed",
|
||||
"action": "Nothing"
|
||||
},
|
||||
{
|
||||
"markerRich": "<strong>WARNING</strong>",
|
||||
"meaning": "Real issue, fix recommended",
|
||||
"action": "Read the control description, plan a fix"
|
||||
},
|
||||
{
|
||||
"markerRich": "<strong>SUGGESTION</strong>",
|
||||
"meaning": "Hardening improvement available",
|
||||
"action": "Apply if it fits your threat model"
|
||||
}
|
||||
],
|
||||
"outro": "Full report and machine-readable data are written to <code>/var/log/lynis.log</code> and <code>/var/log/lynis-report.dat</code> by Lynis itself."
|
||||
},
|
||||
"pairFail2ban": {
|
||||
"title": "Pair with Fail2Ban",
|
||||
"body": "SSH-7408 (MaxAuthTries) is one of the most common warnings. Installing <link>Fail2Ban</link> from ProxMenux clears it automatically because the installer sets <code>MaxAuthTries=3</code> as part of its SSH hardening step. Run Lynis again afterwards to confirm the warning is gone."
|
||||
},
|
||||
"update": {
|
||||
"heading": "Update Lynis",
|
||||
"body": "From the manage menu, <strong>Update Lynis to latest version</strong> runs <code>git pull --quiet</code> inside <code>/opt/lynis</code>. If the directory exists but isn't a Git checkout (e.g. someone copied the files in manually), the script falls back to a full reinstall."
|
||||
},
|
||||
"reinstall": {
|
||||
"heading": "Reinstall / uninstall",
|
||||
"headerAction": "Action",
|
||||
"headerWhat": "What it does",
|
||||
"rows": [
|
||||
{
|
||||
"actionRich": "<strong>Reinstall</strong>",
|
||||
"whatRich": "Removes <code>/opt/lynis</code>, re-clones from GitHub, recreates the wrapper. Use this if the local checkout is corrupted."
|
||||
},
|
||||
{
|
||||
"actionRich": "<strong>Remove</strong>",
|
||||
"whatRich": "Deletes <code>/opt/lynis</code> and <code>/usr/local/bin/lynis</code>. Logs at <code>/var/log/lynis*</code> are kept (they're audit history). An apt-installed Lynis at <code>/usr/bin/lynis</code> is left untouched."
|
||||
}
|
||||
]
|
||||
},
|
||||
"cli": {
|
||||
"heading": "Useful CLI options",
|
||||
"intro": "Once installed, Lynis can be invoked directly from a shell with extra options not exposed by the menu:",
|
||||
"code": "lynis show version # version + build date\nlynis show commands # list every available command\nlynis show details TEST-ID # explain a specific control\nlynis audit system --quick # skip slow tests (e.g. malware scan)\nlynis audit system --pentest # treat host as untrusted (more aggressive)\nlynis update info # check if a newer Lynis is available\n\n# Filter the report log for just the warnings\ngrep \"Warning\" /var/log/lynis.log\n\n# Same, for suggestions only\ngrep \"Suggestion\" /var/log/lynis.log"
|
||||
},
|
||||
"troubleshoot": {
|
||||
"heading": "Troubleshooting",
|
||||
"cloneTitle": "git clone fails during install",
|
||||
"cloneBody": "The host needs network access and DNS to reach <code>github.com</code>. From a console: <code>curl -sI https://github.com</code> and <code>git ls-remote https://github.com/CISOfy/lynis.git</code> will reveal the actual error (DNS, TLS, proxy, repo URL). If a proxy is required, set <code>https_proxy</code> in the environment before re-running the menu.",
|
||||
"notFoundTitle": "lynis: command not found after install",
|
||||
"notFoundIntro": "The wrapper at <code>/usr/local/bin/lynis</code> was either not created or got removed. Quickest fix: reinstall from the menu. Manual fix:",
|
||||
"notFoundCode": "cat > /usr/local/bin/lynis <<'EOF'\n#!/bin/bash\ncd /opt/lynis && ./lynis \"$@\"\nEOF\nchmod +x /usr/local/bin/lynis",
|
||||
"sshTitle": "Audit prints \"Warning: Test SSH-7408 — MaxAuthTries set incorrectly\"",
|
||||
"sshIntro": "The SSH daemon allows too many auth attempts per connection. Either install <link>Fail2Ban</link> from ProxMenux (which sets <code>MaxAuthTries=3</code> automatically) or edit <code>/etc/ssh/sshd_config</code> by hand:",
|
||||
"sshCode": "sed -i 's/^#?MaxAuthTries.*/MaxAuthTries 3/' /etc/ssh/sshd_config\nsystemctl reload sshd",
|
||||
"scoreTitle": "Score went down after a Proxmox upgrade",
|
||||
"scoreBody": "Run <code>lynis update info</code> first — a Lynis update may have added new controls that flag existing config. Update Lynis from the menu, re-audit, and address the new findings."
|
||||
},
|
||||
"files": {
|
||||
"heading": "Files written",
|
||||
"code": "/opt/lynis/ # full Lynis git checkout\n/usr/local/bin/lynis # wrapper script (cd + exec)\n/var/log/lynis.log # human-readable audit log (Lynis itself)\n/var/log/lynis-report.dat # machine-readable report (Lynis itself)"
|
||||
},
|
||||
"sample": {
|
||||
"heading": "Sample report",
|
||||
"intro": "ProxMenux Monitor packages each Lynis run into a multi-page PDF available from the <link>Security tab</link> in the dashboard. The first page is the executive summary — hardening score, system info, security posture overview. Subsequent pages list every warning with explanation and every suggestion ranked by impact, plus the package inventory used during the audit.",
|
||||
"imageAlt": "First page of the Lynis Security Audit Report PDF — executive summary with Hardening Index 71/100, system information block, and security posture overview with firewall, malware scanner and installed packages count",
|
||||
"captionPrefix": "First page of a sample report. The full PDF (",
|
||||
"captionLink": "sample",
|
||||
"captionSuffix": ") continues with detailed warnings, suggestions and the installed-packages list.",
|
||||
"cli": "On the CLI side the same data is in <code>/var/log/lynis-report.dat</code> (machine-readable flat file) and <code>/var/log/lynis.log</code> (the human-readable run log). The PDF is generated on demand by ProxMenux Monitor — running <code>lynis</code> from the command line does not produce one."
|
||||
},
|
||||
"related": {
|
||||
"heading": "Related",
|
||||
"items": [
|
||||
{
|
||||
"href": "/docs/monitor/dashboard/security",
|
||||
"label": "ProxMenux Monitor → Security tab",
|
||||
"tail": " — run the audit, browse historical reports and download the PDF straight from the dashboard."
|
||||
},
|
||||
{
|
||||
"href": "/docs/security/fail2ban",
|
||||
"label": "Fail2Ban",
|
||||
"tailRich": " — implements the SSH brute-force protection that Lynis recommends."
|
||||
},
|
||||
{
|
||||
"href": "/docs/security",
|
||||
"label": "Security overview",
|
||||
"tail": " — back to the section overview."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "HTTPS for ProxMenux Monitor — Proxmox host certificate or custom paths | ProxMenux",
|
||||
"description": "Serve the ProxMenux Monitor over HTTPS using either the Proxmox host certificate (auto-detected, including the Let's Encrypt cert uploaded via the Proxmox ACME tab) or a custom certificate at any path on disk.",
|
||||
"ogTitle": "HTTPS for ProxMenux Monitor — Proxmox host or custom certificate",
|
||||
"ogDescription": "Enable HTTPS on port 8008 with the Proxmox host certificate or any custom .pem / .key pair."
|
||||
},
|
||||
"header": {
|
||||
"title": "HTTPS for ProxMenux Monitor",
|
||||
"description": "Turn HTTPS on for the Monitor (port 8008) using either the Proxmox host certificate the Monitor auto-detects, or a custom certificate located anywhere on disk. The Proxmox option transparently picks the ACME-uploaded certificate when present, so a Let's Encrypt cert managed by the Proxmox UI is reused without an extra renewal job.",
|
||||
"section": "Security"
|
||||
},
|
||||
"intro": {
|
||||
"title": "What this page covers",
|
||||
"body": "How to switch the Monitor from HTTP to HTTPS in the Settings → Security panel, what each certificate source actually points at on disk, how the Proxmox option behaves when the host has a Let's Encrypt cert, and how to set custom paths if you manage certs outside Proxmox."
|
||||
},
|
||||
"wheresetting": {
|
||||
"heading": "Where the setting lives",
|
||||
"body": "Open the Monitor and go to <strong>Settings → Security → HTTPS / SSL</strong>. The panel shows the current state (HTTP or HTTPS), and on a host without HTTPS yet it lists the certificate sources the Monitor was able to detect.",
|
||||
"imageAlt": "Settings → Security → HTTPS / SSL panel in the Monitor showing the HTTPS-off state, the auto-detected Proxmox certificate (subject, issuer, expiry) and the Use Custom Certificate option",
|
||||
"caption": "Settings → Security → HTTPS / SSL panel before activation. The Monitor surfaces the cert Proxmox itself is using and offers it as a one-click source."
|
||||
},
|
||||
"twoways": {
|
||||
"heading": "Two ways to enable HTTPS",
|
||||
"proxmox": {
|
||||
"title": "Use Proxmox certificate",
|
||||
"summary": "One click. The Monitor reuses the certificate Proxmox VE itself serves on port 8006.",
|
||||
"items": [
|
||||
"Auto-detected — no path to type",
|
||||
"Picks the ACME-uploaded cert if present, falls back to the self-signed default",
|
||||
"Renewal happens through Proxmox; the Monitor follows automatically on next start"
|
||||
]
|
||||
},
|
||||
"custom": {
|
||||
"title": "Use custom certificate",
|
||||
"summaryRich": "Point the Monitor at a <code>.pem</code> / <code>.key</code> pair anywhere on disk.",
|
||||
"items": [
|
||||
"Absolute paths only (the Monitor process must be able to read both)",
|
||||
"Useful when certs come from <code>certbot</code>, <code>acme.sh</code> or a wildcard",
|
||||
"You own the renewal — restart the Monitor service after the file changes"
|
||||
]
|
||||
}
|
||||
},
|
||||
"proxmoxCert": {
|
||||
"heading": "Proxmox certificate — what it actually points at",
|
||||
"intro": "Proxmox VE keeps two certificate pairs in <code>/etc/pve/local/</code>:",
|
||||
"table": {
|
||||
"headers": {
|
||||
"file": "File",
|
||||
"origin": "Origin",
|
||||
"when": "When the Monitor uses it"
|
||||
},
|
||||
"rows": [
|
||||
{
|
||||
"fileRich": "<code>pveproxy-ssl.pem</code><br /><code>pveproxy-ssl.key</code>",
|
||||
"originRich": "Custom certificate uploaded via the Proxmox UI — including the Let's Encrypt certificate issued under <em>Datacenter → Node → Certificates → ACME</em>.",
|
||||
"when": "Preferred whenever both files exist. The Monitor will follow the cert Proxmox itself is serving."
|
||||
},
|
||||
{
|
||||
"fileRich": "<code>pve-ssl.pem</code><br /><code>pve-ssl.key</code>",
|
||||
"originRich": "Self-signed certificate generated at install time by the Proxmox PKI.",
|
||||
"whenRich": "Fallback when no <code>pveproxy-ssl.pem</code> is present."
|
||||
}
|
||||
]
|
||||
},
|
||||
"callout": {
|
||||
"title": "Same priority as Proxmox itself",
|
||||
"bodyRich": "<code>pveproxy</code> uses the same selection rule, so picking the Proxmox option in the Monitor always serves the cert the Proxmox web UI is already serving on port 8006. No copying, no separate renewal pipeline."
|
||||
}
|
||||
},
|
||||
"letsencrypt": {
|
||||
"heading": "Getting a Let's Encrypt certificate via Proxmox ACME",
|
||||
"intro": "Proxmox VE ships its own ACME client. Clicking <em>\"Order Certificate Now\"</em> writes the result to <code>/etc/pve/local/pveproxy-ssl.pem</code>, which is exactly what the Monitor reads. The five-step recipe below is the same procedure as the <extlink1>official Proxmox guide</extlink1> — distilled to the commands you actually need to run.",
|
||||
"prereqs": {
|
||||
"title": "Prerequisites",
|
||||
"items": [
|
||||
"The node has a real DNS name (not just an IP) pointing at it.",
|
||||
"<strong>Either</strong> port 80 reachable from the public internet (HTTP-01 challenge, simplest), <strong>or</strong> a DNS provider with API credentials (DNS-01 challenge — works behind NAT, supports wildcards).",
|
||||
"An email address for the ACME account."
|
||||
]
|
||||
},
|
||||
"step1": {
|
||||
"heading": "Step 1 — Register the ACME account",
|
||||
"introRich": "Replace the email with yours. The account name <code>default</code> is just a label — you can use any string.",
|
||||
"code": "pvenode acme account register default you@example.com",
|
||||
"afterRich": "Proxmox prompts you to accept the Let's Encrypt terms of service. After that the account is persisted under <code>/etc/pve/priv/acme/</code> and the ACME tab in the GUI will show it."
|
||||
},
|
||||
"step2": {
|
||||
"heading": "Step 2 — Pick a challenge type",
|
||||
"http01Rich": "<strong>HTTP-01</strong> is the easiest: it's built in, no extra plugin. Let's Encrypt connects to <code>http://<your-host>/.well-known/acme-challenge/...</code> on port 80, so port 80 must be open from the public internet to your node — typically a port forward on your router.",
|
||||
"dns01Rich": "<strong>DNS-01</strong> works without exposing port 80 (good for homelabs behind CG-NAT) and is the only option for wildcard certificates. You add a DNS plugin once with your provider's API token. Cloudflare example:",
|
||||
"code": "pvenode acme plugin add dns cf \\\n --api cloudflare \\\n --data CF_Token=YOUR_CLOUDFLARE_API_TOKEN",
|
||||
"outroRich": "For other providers (Gandi, OVH, AWS Route 53, etc.) check <code>pvenode acme plugin add dns --help</code> — Proxmox ships <extlink2>all acme.sh DNS plugins</extlink2>."
|
||||
},
|
||||
"step3": {
|
||||
"heading": "Step 3 — Bind the domain to your node",
|
||||
"http01Rich": "For HTTP-01 (uses the built-in <code>standalone</code> plugin):",
|
||||
"code1": "pvenode config set --acme domains=host.example.com,account=default",
|
||||
"dns01": "For DNS-01 with the Cloudflare plugin from Step 2:",
|
||||
"code2": "pvenode config set --acmedomain0 domain=host.example.com,plugin=cf\npvenode config set --acme account=default",
|
||||
"wildcardRich": "Wildcard? Add <code>domain=*.example.com</code> on a separate <code>--acmedomainN</code> entry. Wildcards require DNS-01."
|
||||
},
|
||||
"step4": {
|
||||
"heading": "Step 4 — Order the certificate",
|
||||
"code": "pvenode acme cert order",
|
||||
"afterRich": "First run typically takes 30–60 seconds while the challenge propagates. On success Proxmox writes <code>/etc/pve/local/pveproxy-ssl.pem</code> + <code>.key</code>, restarts <code>pveproxy</code>, and a renewal cron is scheduled automatically (Let's Encrypt certs are valid 90 days; Proxmox renews at 60)."
|
||||
},
|
||||
"step5": {
|
||||
"heading": "Step 5 — Verify the issuer",
|
||||
"code": "openssl x509 -in /etc/pve/local/pveproxy-ssl.pem -noout -issuer",
|
||||
"afterRich": "Should print an issuer starting with <code>O = Let's Encrypt</code>. If it instead reads <code>CN = Proxmox Virtual Environment</code> the order failed and the file is still the self-signed PVE cert — re-run <code>pvenode acme cert order --debug 1</code> to see why."
|
||||
},
|
||||
"gui": {
|
||||
"title": "Prefer the GUI? Same five steps",
|
||||
"bodyRich": "<em>Datacenter → ACME</em> registers the account, <em>Datacenter → ACME → Plugins</em> adds the DNS plugin, <em>Node → Certificates → ACME</em> binds the domain, and <em>Order Certificates Now</em> runs Step 4. The CLI commands above are useful for scripting and for headless / CLI-only setups."
|
||||
}
|
||||
},
|
||||
"switchToHttps": {
|
||||
"heading": "Switch the Monitor to HTTPS",
|
||||
"bodyRich": "Once <code>/etc/pve/local/pveproxy-ssl.pem</code> is signed by Let's Encrypt, the Monitor side is one click: open <strong>Settings → Security → HTTPS / SSL</strong>, confirm the issuer shown in the detected-certificate panel reads <em>Let's Encrypt</em> (and not the local Proxmox CA), and click <strong>Use Proxmox Certificate</strong>. The Monitor service restarts and the next browser load is HTTPS on port 8008 — no certificate warning, since the chain is publicly trusted."
|
||||
},
|
||||
"custom": {
|
||||
"heading": "Custom certificate — when to use it",
|
||||
"intro": "Click <strong>Use Custom Certificate</strong> to enter two absolute paths:",
|
||||
"items": [
|
||||
"<strong>Certificate</strong> — full chain in PEM (<code>.pem</code> or <code>.crt</code>).",
|
||||
"<strong>Private key</strong> — matching key in PEM (<code>.key</code>)."
|
||||
],
|
||||
"outro": "Both files are read by the Monitor process at startup. Make sure they remain readable by the user the systemd unit runs as (root by default). Common locations when ACME is managed outside Proxmox:",
|
||||
"code": "# certbot\n/etc/letsencrypt/live/<your-host>/fullchain.pem\n/etc/letsencrypt/live/<your-host>/privkey.pem\n\n# acme.sh\n~/.acme.sh/<your-host>_ecc/fullchain.cer\n~/.acme.sh/<your-host>_ecc/<your-host>.key",
|
||||
"symlinkCallout": {
|
||||
"title": "Symlink targets vs. files",
|
||||
"bodyRich": "<code>certbot</code> stores the actual files in <code>/etc/letsencrypt/archive/</code> and the <code>live/</code> path is a symlink. Point the Monitor at the <code>live/</code> symlink, not the <code>archive/</code> file — that way each renewal cycle simply rewrites the symlink target and the Monitor picks up the new cert at the next service start."
|
||||
}
|
||||
},
|
||||
"afterHttps": {
|
||||
"heading": "After enabling HTTPS",
|
||||
"bodyRich": "Saving the change writes <code>/etc/proxmenux/ssl_config.json</code> and triggers a restart of the <code>proxmenux-monitor</code> systemd unit. The browser tab will lose its current connection — reload it on <code>https://<host>:8008/</code>. The first load with a Let's Encrypt cert should show no warning; with the Proxmox self-signed cert the browser will require an exception, the same one as for port 8006.",
|
||||
"reverse": {
|
||||
"heading": "Reverse proxies and webhooks",
|
||||
"bodyRich": "When the Monitor switches to HTTPS, Proxmox VE webhook URLs registered for notifications also flip from <code>http://</code> to <code>https://</code> automatically. Existing webhook entries are rewritten the next time a notification rule is saved or re-detected, so no manual edit of the Proxmox notification config is needed."
|
||||
}
|
||||
},
|
||||
"trustCa": {
|
||||
"heading": "Trust the Proxmox self-signed CA",
|
||||
"intro1Rich": "If you prefer to keep the default Proxmox-generated certificate (no ACME), you can stop the browser warning by importing the cluster's root CA into the OS or browser trust store. The Monitor will keep auto-detecting the same <code>/etc/pve/local/pveproxy-ssl.pem</code>; the only thing that changes is that the device viewing the dashboard now recognises the issuer.",
|
||||
"intro2Rich": "The CA file lives at <code>/etc/pve/pve-root-ca.pem</code> on every node. In a cluster the path is on the shared <code>pmxcfs</code> filesystem so all nodes share the same root, and a single import covers the whole datacenter. Copy it to your machine:",
|
||||
"code": "scp root@<your-host>:/etc/pve/pve-root-ca.pem ./pve-root-ca.pem",
|
||||
"thenImport": "Then import it on the client side:",
|
||||
"items": [
|
||||
"<strong>Linux (system-wide):</strong> <code>sudo cp pve-root-ca.pem /usr/local/share/ca-certificates/pve-root-ca.crt</code> followed by <code>sudo update-ca-certificates</code>. Browsers using the system store (Chromium, Edge) pick it up after restart; Firefox uses its own store and needs the manual import below.",
|
||||
"<strong>macOS:</strong> double-click the <code>.pem</code> file, Keychain Access opens → add it to the <em>System</em> keychain → set <em>Trust → Always Trust</em>.",
|
||||
"<strong>Windows:</strong> right-click the file → <em>Install Certificate</em> → place it in <em>Trusted Root Certification Authorities</em>.",
|
||||
"<strong>Firefox (any OS):</strong> <em>Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import</em>, tick <em>Trust this CA to identify websites</em>."
|
||||
],
|
||||
"standalone": {
|
||||
"title": "Standalone nodes outside a cluster",
|
||||
"bodyRich": "Each non-clustered Proxmox host has its own <code>pve-root-ca.pem</code>. If you manage several standalone hosts, repeat the copy/import for each, or join them to a cluster so they share a single root."
|
||||
}
|
||||
},
|
||||
"disable": {
|
||||
"heading": "Disabling HTTPS",
|
||||
"bodyRich": "Click <strong>Disable HTTPS</strong> in the same panel. The Monitor service restarts back on plain HTTP — useful if a custom certificate file becomes unreadable and the service won't come back up. There is no separate uninstall step; the cert files themselves are not touched.",
|
||||
"stateCallout": {
|
||||
"title": "Where the state lives",
|
||||
"bodyRich": "<code>/etc/proxmenux/ssl_config.json</code> stores the active cert paths and the source (<code>none</code>, <code>proxmox</code>, <code>custom</code>). Deleting the file is equivalent to disabling HTTPS — on next start the Monitor falls back to HTTP."
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user