sysreport 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/CONTRIBUTING.md +33 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/SECURITY.md +15 -0
- package/VERSION +1 -0
- package/bin/sysreport +51 -0
- package/package.json +40 -0
- package/src/sysreport/core.sh +201 -0
- package/src/sysreport/modules/10-system.sh +32 -0
- package/src/sysreport/modules/20-identity.sh +32 -0
- package/src/sysreport/modules/30-network.sh +46 -0
- package/src/sysreport/modules/40-services.sh +38 -0
- package/src/sysreport/modules/50-webstack.sh +61 -0
- package/src/sysreport/modules/60-database.sh +29 -0
- package/src/sysreport/modules/70-security.sh +85 -0
- package/src/sysreport/modules/80-optimization.sh +52 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.3
|
|
4
|
+
|
|
5
|
+
- Fixed npm global installs by resolving symlinked CLI launchers before locating runtime files.
|
|
6
|
+
- Prepared npm metadata and GitHub release packaging for RPM/Debian artifacts.
|
|
7
|
+
- Ensured RPM/Debian packages own runtime directories so package removal is clean.
|
|
8
|
+
|
|
9
|
+
## 1.1.2
|
|
10
|
+
|
|
11
|
+
- Improved WHM/cPanel output formatting for PHP-FPM units.
|
|
12
|
+
- Added CSF, LFD, Imunify360, firewalld, and ufw service status checks.
|
|
13
|
+
- Kept `--no-color` output clean by suppressing fastfetch's colored block.
|
|
14
|
+
|
|
15
|
+
## 1.1.1
|
|
16
|
+
|
|
17
|
+
- Fixed installed CLI version detection by installing `VERSION` with the runtime files.
|
|
18
|
+
- Included `VERSION` in nFPM and RPM package layouts.
|
|
19
|
+
|
|
20
|
+
## 1.1.0
|
|
21
|
+
|
|
22
|
+
- Rebuilt SysReport as a modular CLI with a small launcher and reusable report modules.
|
|
23
|
+
- Added CI smoke tests and GitHub release archive automation.
|
|
24
|
+
- Added public project docs: README, contributing guide, security policy, license, and packaging metadata.
|
|
25
|
+
- Added safer runtime behavior for public use: report-only execution, section filtering, and graceful skips for missing tools.
|
|
26
|
+
|
|
27
|
+
## 1.0.2
|
|
28
|
+
|
|
29
|
+
- Refactored the CLI into a modular runtime under `src/sysreport/`.
|
|
30
|
+
- Added section filtering with `--section` and discovery with `--list-sections`.
|
|
31
|
+
- Removed automatic dependency installation during report execution.
|
|
32
|
+
- Updated package metadata and install paths for public distribution.
|
|
33
|
+
|
|
34
|
+
## 1.0.0
|
|
35
|
+
|
|
36
|
+
- Initial release.
|
|
37
|
+
- Hardware audit.
|
|
38
|
+
- Network audit.
|
|
39
|
+
- PHP audit.
|
|
40
|
+
- MySQL audit.
|
|
41
|
+
- Security audit.
|
|
42
|
+
- SEO audit.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve SysReport.
|
|
4
|
+
|
|
5
|
+
## Local Checks
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
make check
|
|
9
|
+
bash bin/sysreport --list-sections
|
|
10
|
+
bash bin/sysreport --section system --no-color
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Adding a Report Section
|
|
14
|
+
|
|
15
|
+
Create a new file under `src/sysreport/modules/` and register it:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
report_example() {
|
|
19
|
+
sysreport_section "Example"
|
|
20
|
+
sysreport_item "Status" "ok"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
sysreport_register_section "example" "Example report" "report_example"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Keep modules read-only by default. A report command should never install packages, restart services, edit configuration, or delete files.
|
|
27
|
+
|
|
28
|
+
## Style
|
|
29
|
+
|
|
30
|
+
- Prefer portable Bash and common Linux utilities.
|
|
31
|
+
- Check for optional commands with `sysreport_have`.
|
|
32
|
+
- If a command is missing or access is denied, print a skipped or unknown result instead of failing the whole report.
|
|
33
|
+
- Keep output useful for humans first.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amir Hossein Khateri
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# SysReport
|
|
2
|
+
|
|
3
|
+
SysReport is a lightweight Linux server audit CLI for sysadmins, DevOps engineers, and hosting operators. Run one command and get a practical summary of the server's health, identity, network, web stack, databases, security posture, and optimization signals.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
sysreport
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Highlights
|
|
10
|
+
|
|
11
|
+
- Modular Bash architecture: each report area lives in `src/sysreport/modules/`.
|
|
12
|
+
- Safe by default: it does not install dependencies or change server configuration while reporting.
|
|
13
|
+
- Works on generic Linux servers and adds extra context when cPanel/WHM, PHP, MySQL, Redis, Memcached, or common firewalls are detected.
|
|
14
|
+
- Supports targeted checks with `--section`.
|
|
15
|
+
- Friendly to package managers: npm, deb/rpm layouts, and manual install scripts are included.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Manual
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/amirkhateri/sysreport.git
|
|
23
|
+
cd sysreport
|
|
24
|
+
bash scripts/install/install.sh
|
|
25
|
+
sysreport
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### npm
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install -g sysreport
|
|
32
|
+
sysreport
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Debian / Ubuntu and RPM
|
|
36
|
+
|
|
37
|
+
Download packages from the GitHub release page, or install the RPM directly with `dnf`:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
VERSION=1.1.3
|
|
41
|
+
sudo dnf install -y "https://github.com/amirkhateri/sysreport/releases/download/v${VERSION}/sysreport-${VERSION}-1.noarch.rpm"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Debian/Ubuntu users can install the `.deb` package from the same release:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
VERSION=1.1.3
|
|
48
|
+
curl -LO "https://github.com/amirkhateri/sysreport/releases/download/v${VERSION}/sysreport_${VERSION}_all.deb"
|
|
49
|
+
sudo apt install ./sysreport_${VERSION}_all.deb
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Package templates are available under `templates/`, and release automation publishes `.deb` and `.rpm` artifacts.
|
|
53
|
+
|
|
54
|
+
For GitHub releases, download the `sysreport-<version>.tar.gz` archive, extract it, and run the installer:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
tar -xzf sysreport-<version>.tar.gz
|
|
58
|
+
cd sysreport-<version>
|
|
59
|
+
bash scripts/install/install.sh
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
sysreport # run the full report
|
|
66
|
+
sysreport --list-sections # show available sections
|
|
67
|
+
sysreport --section system --section security
|
|
68
|
+
sysreport --no-color
|
|
69
|
+
sysreport --version
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Current sections:
|
|
73
|
+
|
|
74
|
+
- `system`
|
|
75
|
+
- `identity`
|
|
76
|
+
- `network`
|
|
77
|
+
- `services`
|
|
78
|
+
- `webstack`
|
|
79
|
+
- `database`
|
|
80
|
+
- `security`
|
|
81
|
+
- `optimization`
|
|
82
|
+
|
|
83
|
+
You can customize network ping targets:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
SYSREPORT_PING_TARGETS="1.1.1.1 github.com example.com" sysreport --section network
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Optional Dependencies
|
|
90
|
+
|
|
91
|
+
SysReport runs without these tools, but it reports more detail when they exist:
|
|
92
|
+
|
|
93
|
+
- `curl` for public IP detection
|
|
94
|
+
- `jq` for IP geolocation parsing
|
|
95
|
+
- `fastfetch` for an optional system profile block
|
|
96
|
+
- `systemctl`, `ss`, `ip`, `ping`, `free`, `df`, `awk`, `sed`, `grep`
|
|
97
|
+
- `mysql`, `psql`, `php`, `nginx`, `httpd` or `apache2` for stack-specific checks
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
Run locally:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
make run
|
|
105
|
+
make sections
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Syntax check:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
make check
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Add a new report module by creating a file in `src/sysreport/modules/`:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
report_example() {
|
|
118
|
+
sysreport_section "Example"
|
|
119
|
+
sysreport_item "Status" "ok"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
sysreport_register_section "example" "Example report" "report_example"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Philosophy
|
|
126
|
+
|
|
127
|
+
SysReport should be useful on the first run, readable by humans, conservative on production servers, and easy to extend. It reports what it can see and skips what is unavailable instead of failing the whole run.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
SysReport is a read-only audit tool. Report modules should not change server state, install packages, restart services, or expose secrets.
|
|
4
|
+
|
|
5
|
+
## Reporting a Vulnerability
|
|
6
|
+
|
|
7
|
+
Please open a private security advisory or contact the maintainer from the repository profile if you find a vulnerability.
|
|
8
|
+
|
|
9
|
+
When reporting, include:
|
|
10
|
+
|
|
11
|
+
- affected version or commit
|
|
12
|
+
- command used
|
|
13
|
+
- operating system
|
|
14
|
+
- impact
|
|
15
|
+
- suggested fix, if known
|
package/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.1.3
|
package/bin/sysreport
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -o pipefail
|
|
4
|
+
|
|
5
|
+
resolve_lib_dir() {
|
|
6
|
+
local source bin_dir candidate
|
|
7
|
+
source="${BASH_SOURCE[0]}"
|
|
8
|
+
|
|
9
|
+
while [[ -L "$source" ]]; do
|
|
10
|
+
bin_dir="$(cd -- "$(dirname -- "$source")" >/dev/null 2>&1 && pwd -P)"
|
|
11
|
+
source="$(readlink "$source")"
|
|
12
|
+
[[ "$source" != /* ]] && source="$bin_dir/$source"
|
|
13
|
+
done
|
|
14
|
+
|
|
15
|
+
bin_dir="$(cd -- "$(dirname -- "$source")" >/dev/null 2>&1 && pwd -P)"
|
|
16
|
+
|
|
17
|
+
if [[ -n "${SYSREPORT_LIB_DIR:-}" && -f "$SYSREPORT_LIB_DIR/core.sh" ]]; then
|
|
18
|
+
printf '%s\n' "$SYSREPORT_LIB_DIR"
|
|
19
|
+
return 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
for candidate in \
|
|
23
|
+
"$bin_dir/../src/sysreport" \
|
|
24
|
+
"$bin_dir/../lib/sysreport" \
|
|
25
|
+
"/usr/local/lib/sysreport" \
|
|
26
|
+
"/usr/lib/sysreport"; do
|
|
27
|
+
if [[ -f "$candidate/core.sh" ]]; then
|
|
28
|
+
printf '%s\n' "$candidate"
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
done
|
|
32
|
+
|
|
33
|
+
return 1
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
SYSREPORT_LIB_DIR="$(resolve_lib_dir)" || {
|
|
37
|
+
echo "sysreport: unable to find runtime files. Set SYSREPORT_LIB_DIR to the sysreport library path." >&2
|
|
38
|
+
exit 1
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# shellcheck source=/dev/null
|
|
42
|
+
source "$SYSREPORT_LIB_DIR/core.sh"
|
|
43
|
+
|
|
44
|
+
shopt -s nullglob
|
|
45
|
+
for module in "$SYSREPORT_LIB_DIR"/modules/*.sh; do
|
|
46
|
+
# shellcheck source=/dev/null
|
|
47
|
+
source "$module"
|
|
48
|
+
done
|
|
49
|
+
shopt -u nullglob
|
|
50
|
+
|
|
51
|
+
sysreport_main "$@"
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sysreport",
|
|
3
|
+
"version": "1.1.3",
|
|
4
|
+
"description": "Linux server audit and operations summary CLI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"os": [
|
|
7
|
+
"linux"
|
|
8
|
+
],
|
|
9
|
+
"author": "Amir Hossein Khateri",
|
|
10
|
+
"homepage": "https://github.com/amirkhateri/sysreport",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/amirkhateri/sysreport.git"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"sysreport": "bin/sysreport"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org/"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"bin/",
|
|
24
|
+
"src/",
|
|
25
|
+
"README.md",
|
|
26
|
+
"CHANGELOG.md",
|
|
27
|
+
"CONTRIBUTING.md",
|
|
28
|
+
"SECURITY.md",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"VERSION"
|
|
31
|
+
],
|
|
32
|
+
"keywords": [
|
|
33
|
+
"linux",
|
|
34
|
+
"server",
|
|
35
|
+
"audit",
|
|
36
|
+
"sysadmin",
|
|
37
|
+
"devops",
|
|
38
|
+
"monitoring"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
SYSREPORT_NAME="sysreport"
|
|
4
|
+
SYSREPORT_DESCRIPTION="Linux server audit and operations summary"
|
|
5
|
+
SYSREPORT_VERSION="${SYSREPORT_VERSION:-dev}"
|
|
6
|
+
|
|
7
|
+
if [[ -z "${SYSREPORT_ROOT:-}" ]]; then
|
|
8
|
+
SYSREPORT_ROOT="$(cd -- "${SYSREPORT_LIB_DIR:-$(pwd)}/../.." >/dev/null 2>&1 && pwd -P)"
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
if [[ -n "${SYSREPORT_LIB_DIR:-}" && -f "$SYSREPORT_LIB_DIR/VERSION" ]]; then
|
|
12
|
+
SYSREPORT_VERSION="$(tr -d '[:space:]' < "$SYSREPORT_LIB_DIR/VERSION")"
|
|
13
|
+
elif [[ -f "$SYSREPORT_ROOT/VERSION" ]]; then
|
|
14
|
+
SYSREPORT_VERSION="$(tr -d '[:space:]' < "$SYSREPORT_ROOT/VERSION")"
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
SYSREPORT_SECTION_IDS=()
|
|
18
|
+
SYSREPORT_SECTION_TITLES=()
|
|
19
|
+
SYSREPORT_SECTION_FUNCS=()
|
|
20
|
+
SYSREPORT_SELECTED_SECTIONS=()
|
|
21
|
+
SYSREPORT_COLOR=1
|
|
22
|
+
|
|
23
|
+
if [[ ! -t 1 || -n "${NO_COLOR:-}" || "${TERM:-}" == "dumb" ]]; then
|
|
24
|
+
SYSREPORT_COLOR=0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
sysreport_use_color() {
|
|
28
|
+
[[ "$SYSREPORT_COLOR" -eq 1 ]]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
sysreport_color() {
|
|
32
|
+
local code="$1"
|
|
33
|
+
if sysreport_use_color; then
|
|
34
|
+
printf '\033[%sm' "$code"
|
|
35
|
+
fi
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
sysreport_refresh_colors() {
|
|
39
|
+
SR_RESET="$(sysreport_color 0)"
|
|
40
|
+
SR_BOLD="$(sysreport_color 1)"
|
|
41
|
+
SR_BLUE="$(sysreport_color '0;34')"
|
|
42
|
+
SR_CYAN="$(sysreport_color '0;36')"
|
|
43
|
+
SR_GREEN="$(sysreport_color '0;32')"
|
|
44
|
+
SR_YELLOW="$(sysreport_color '1;33')"
|
|
45
|
+
SR_RED="$(sysreport_color '0;31')"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
sysreport_refresh_colors
|
|
49
|
+
|
|
50
|
+
sysreport_have() {
|
|
51
|
+
command -v "$1" >/dev/null 2>&1
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
sysreport_read_os_release() {
|
|
55
|
+
if [[ -r /etc/os-release ]]; then
|
|
56
|
+
(
|
|
57
|
+
# shellcheck disable=SC1091
|
|
58
|
+
source /etc/os-release
|
|
59
|
+
printf '%s\n' "${PRETTY_NAME:-${NAME:-Linux}}"
|
|
60
|
+
)
|
|
61
|
+
else
|
|
62
|
+
uname -s
|
|
63
|
+
fi
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
sysreport_register_section() {
|
|
67
|
+
local id="$1" title="$2" fn="$3"
|
|
68
|
+
SYSREPORT_SECTION_IDS+=("$id")
|
|
69
|
+
SYSREPORT_SECTION_TITLES+=("$title")
|
|
70
|
+
SYSREPORT_SECTION_FUNCS+=("$fn")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
sysreport_is_selected() {
|
|
74
|
+
local id="$1" selected
|
|
75
|
+
if [[ "${#SYSREPORT_SELECTED_SECTIONS[@]}" -eq 0 ]]; then
|
|
76
|
+
return 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
for selected in "${SYSREPORT_SELECTED_SECTIONS[@]}"; do
|
|
80
|
+
[[ "$selected" == "$id" ]] && return 0
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
return 1
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
sysreport_header() {
|
|
87
|
+
printf '%s\n' "${SR_BLUE}${SR_BOLD}============================================================${SR_RESET}"
|
|
88
|
+
printf '%s\n' "${SR_CYAN}${SR_BOLD} SysReport ${SYSREPORT_VERSION} - ${SYSREPORT_DESCRIPTION}${SR_RESET}"
|
|
89
|
+
printf '%s\n' "${SR_BLUE}${SR_BOLD}============================================================${SR_RESET}"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
sysreport_section() {
|
|
93
|
+
printf '\n%s\n' "${SR_BLUE}${SR_BOLD}-- $1 --${SR_RESET}"
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
sysreport_item() {
|
|
97
|
+
printf '%b%s:%b %s\n' "${SR_GREEN}" "$1" "${SR_RESET}" "${2:-}"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
sysreport_ok() {
|
|
101
|
+
printf ' [%bOK%b] %s\n' "$SR_GREEN" "$SR_RESET" "$1"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
sysreport_warn() {
|
|
105
|
+
printf ' [%bWARN%b] %s\n' "$SR_YELLOW" "$SR_RESET" "$1"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
sysreport_fail() {
|
|
109
|
+
printf ' [%bFAIL%b] %s\n' "$SR_RED" "$SR_RESET" "$1"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
sysreport_unknown() {
|
|
113
|
+
printf ' [%bSKIP%b] %s\n' "$SR_YELLOW" "$SR_RESET" "$1"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
sysreport_usage() {
|
|
117
|
+
cat <<EOF
|
|
118
|
+
SysReport - Linux server audit and operations summary
|
|
119
|
+
|
|
120
|
+
Usage:
|
|
121
|
+
sysreport [options]
|
|
122
|
+
|
|
123
|
+
Options:
|
|
124
|
+
-h, --help Show this help message
|
|
125
|
+
-v, --version Show version
|
|
126
|
+
--no-color Disable colored output
|
|
127
|
+
--list-sections List available report sections
|
|
128
|
+
--section <id> Run one section; repeat to run multiple sections
|
|
129
|
+
|
|
130
|
+
Examples:
|
|
131
|
+
sysreport
|
|
132
|
+
sysreport --section system --section security
|
|
133
|
+
NO_COLOR=1 sysreport
|
|
134
|
+
EOF
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
sysreport_list_sections() {
|
|
138
|
+
local i
|
|
139
|
+
for i in "${!SYSREPORT_SECTION_IDS[@]}"; do
|
|
140
|
+
printf '%-14s %s\n' "${SYSREPORT_SECTION_IDS[$i]}" "${SYSREPORT_SECTION_TITLES[$i]}"
|
|
141
|
+
done
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
sysreport_parse_args() {
|
|
145
|
+
while [[ "$#" -gt 0 ]]; do
|
|
146
|
+
case "$1" in
|
|
147
|
+
-h|--help)
|
|
148
|
+
sysreport_usage
|
|
149
|
+
exit 0
|
|
150
|
+
;;
|
|
151
|
+
-v|--version)
|
|
152
|
+
printf '%s\n' "$SYSREPORT_VERSION"
|
|
153
|
+
exit 0
|
|
154
|
+
;;
|
|
155
|
+
--no-color)
|
|
156
|
+
SYSREPORT_COLOR=0
|
|
157
|
+
;;
|
|
158
|
+
--list-sections)
|
|
159
|
+
sysreport_list_sections
|
|
160
|
+
exit 0
|
|
161
|
+
;;
|
|
162
|
+
--section)
|
|
163
|
+
if [[ -z "${2:-}" ]]; then
|
|
164
|
+
echo "sysreport: --section requires a section id" >&2
|
|
165
|
+
exit 2
|
|
166
|
+
fi
|
|
167
|
+
SYSREPORT_SELECTED_SECTIONS+=("$2")
|
|
168
|
+
shift
|
|
169
|
+
;;
|
|
170
|
+
*)
|
|
171
|
+
echo "sysreport: unknown option: $1" >&2
|
|
172
|
+
echo "Try 'sysreport --help'." >&2
|
|
173
|
+
exit 2
|
|
174
|
+
;;
|
|
175
|
+
esac
|
|
176
|
+
shift
|
|
177
|
+
done
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
sysreport_main() {
|
|
181
|
+
local i fn matched=0
|
|
182
|
+
sysreport_parse_args "$@"
|
|
183
|
+
sysreport_refresh_colors
|
|
184
|
+
sysreport_header
|
|
185
|
+
|
|
186
|
+
for i in "${!SYSREPORT_SECTION_IDS[@]}"; do
|
|
187
|
+
if sysreport_is_selected "${SYSREPORT_SECTION_IDS[$i]}"; then
|
|
188
|
+
matched=1
|
|
189
|
+
fn="${SYSREPORT_SECTION_FUNCS[$i]}"
|
|
190
|
+
"$fn"
|
|
191
|
+
fi
|
|
192
|
+
done
|
|
193
|
+
|
|
194
|
+
if [[ "$matched" -eq 0 ]]; then
|
|
195
|
+
echo "sysreport: no matching sections selected" >&2
|
|
196
|
+
exit 2
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
printf '\n%s\n' "${SR_BLUE}${SR_BOLD}============================================================${SR_RESET}"
|
|
200
|
+
printf '%s\n' "${SR_GREEN}${SR_BOLD}Report complete.${SR_RESET}"
|
|
201
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_system() {
|
|
4
|
+
local os kernel uptime_text load_avg cpu_cores memory_line swap_line root_usage
|
|
5
|
+
|
|
6
|
+
sysreport_section "System Summary"
|
|
7
|
+
|
|
8
|
+
os="$(sysreport_read_os_release)"
|
|
9
|
+
kernel="$(uname -r 2>/dev/null || echo unknown)"
|
|
10
|
+
uptime_text="$(uptime -p 2>/dev/null || uptime 2>/dev/null || echo unknown)"
|
|
11
|
+
load_avg="$(uptime 2>/dev/null | awk -F'load average: ' '{print $2}' || true)"
|
|
12
|
+
cpu_cores="$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo unknown)"
|
|
13
|
+
memory_line="$(free -h 2>/dev/null | awk '/^Mem:/ {print $3 " used / " $2 " total"}')"
|
|
14
|
+
swap_line="$(free -h 2>/dev/null | awk '/^Swap:/ {print $3 " used / " $2 " total"}')"
|
|
15
|
+
root_usage="$(df -h / 2>/dev/null | awk 'NR==2 {print $5 " used on " $1 " (" $4 " free)"}')"
|
|
16
|
+
|
|
17
|
+
sysreport_item "OS" "$os"
|
|
18
|
+
sysreport_item "Kernel" "$kernel"
|
|
19
|
+
sysreport_item "Uptime" "$uptime_text"
|
|
20
|
+
sysreport_item "CPU cores" "$cpu_cores"
|
|
21
|
+
sysreport_item "Load average" "${load_avg:-unknown}"
|
|
22
|
+
sysreport_item "Memory" "${memory_line:-unknown}"
|
|
23
|
+
sysreport_item "Swap" "${swap_line:-unknown}"
|
|
24
|
+
sysreport_item "Root filesystem" "${root_usage:-unknown}"
|
|
25
|
+
|
|
26
|
+
if sysreport_have fastfetch && sysreport_use_color; then
|
|
27
|
+
printf '\n'
|
|
28
|
+
fastfetch --pipe false 2>/dev/null || true
|
|
29
|
+
fi
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
sysreport_register_section "system" "System summary" "report_system"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_identity() {
|
|
4
|
+
local hostname_value private_ipv4 public_ipv4 public_ipv6 location ip_info country city
|
|
5
|
+
|
|
6
|
+
sysreport_section "Identity and Location"
|
|
7
|
+
|
|
8
|
+
hostname_value="$(hostname -f 2>/dev/null || hostname 2>/dev/null || echo unknown)"
|
|
9
|
+
private_ipv4="$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}')"
|
|
10
|
+
|
|
11
|
+
if sysreport_have curl; then
|
|
12
|
+
public_ipv4="$(curl -fsS --max-time 3 -4 https://icanhazip.com 2>/dev/null | head -n1 || true)"
|
|
13
|
+
public_ipv6="$(curl -fsS --max-time 3 -6 https://icanhazip.com 2>/dev/null | head -n1 || true)"
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
sysreport_item "Hostname" "$hostname_value"
|
|
17
|
+
sysreport_item "Primary IPv4" "${private_ipv4:-unknown}"
|
|
18
|
+
sysreport_item "Public IPv4" "${public_ipv4:-unknown}"
|
|
19
|
+
sysreport_item "Public IPv6" "${public_ipv6:-not detected}"
|
|
20
|
+
|
|
21
|
+
if [[ -n "${public_ipv4:-}" ]] && sysreport_have curl && sysreport_have jq; then
|
|
22
|
+
ip_info="$(curl -fsS --max-time 4 "http://ip-api.com/json/${public_ipv4}" 2>/dev/null || true)"
|
|
23
|
+
country="$(printf '%s' "$ip_info" | jq -r '.country // empty' 2>/dev/null || true)"
|
|
24
|
+
city="$(printf '%s' "$ip_info" | jq -r '.city // empty' 2>/dev/null || true)"
|
|
25
|
+
location="$(printf '%s, %s' "${city:-unknown}" "${country:-unknown}")"
|
|
26
|
+
sysreport_item "Geolocation" "$location"
|
|
27
|
+
else
|
|
28
|
+
sysreport_item "Geolocation" "skipped (requires curl, jq, and public IPv4)"
|
|
29
|
+
fi
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
sysreport_register_section "identity" "Host identity and public IP" "report_identity"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_network_ping() {
|
|
4
|
+
local target="$1" ms
|
|
5
|
+
if ! sysreport_have ping; then
|
|
6
|
+
sysreport_unknown "ping command not available"
|
|
7
|
+
return 0
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
ms="$(ping -c 1 -W 2 "$target" 2>/dev/null | awk -F'time=' '/time=/{print $2}' | awk '{print $1; exit}')"
|
|
11
|
+
if [[ -n "$ms" ]]; then
|
|
12
|
+
sysreport_ok "$target reachable (${ms} ms)"
|
|
13
|
+
else
|
|
14
|
+
sysreport_warn "$target timeout or unreachable"
|
|
15
|
+
fi
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
report_network() {
|
|
19
|
+
local targets target
|
|
20
|
+
|
|
21
|
+
sysreport_section "Network"
|
|
22
|
+
|
|
23
|
+
targets="${SYSREPORT_PING_TARGETS:-1.1.1.1 google.com github.com}"
|
|
24
|
+
sysreport_item "Ping targets" "$targets"
|
|
25
|
+
for target in $targets; do
|
|
26
|
+
report_network_ping "$target"
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
printf '\n'
|
|
30
|
+
sysreport_item "DNS resolvers" ""
|
|
31
|
+
if [[ -r /etc/resolv.conf ]]; then
|
|
32
|
+
awk '/^nameserver/ {print " " $2}' /etc/resolv.conf
|
|
33
|
+
else
|
|
34
|
+
sysreport_unknown "/etc/resolv.conf is not readable"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
printf '\n'
|
|
38
|
+
sysreport_item "Listening TCP ports" ""
|
|
39
|
+
if sysreport_have ss; then
|
|
40
|
+
ss -H -tln 2>/dev/null | awk '{print " " $4}' | sed 's/.*://' | sort -n | uniq | head -n 30
|
|
41
|
+
else
|
|
42
|
+
sysreport_unknown "ss command not available"
|
|
43
|
+
fi
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
sysreport_register_section "network" "Network diagnostics" "report_network"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_service_status() {
|
|
4
|
+
local label="$1" unit="$2"
|
|
5
|
+
|
|
6
|
+
if ! sysreport_have systemctl; then
|
|
7
|
+
sysreport_unknown "systemctl not available for $label"
|
|
8
|
+
return 0
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
if systemctl list-unit-files --no-legend "$unit" 2>/dev/null | grep -q . || \
|
|
12
|
+
systemctl list-units --no-legend "$unit" 2>/dev/null | grep -q .; then
|
|
13
|
+
if systemctl is-active --quiet "$unit" 2>/dev/null; then
|
|
14
|
+
sysreport_ok "$label active ($unit)"
|
|
15
|
+
else
|
|
16
|
+
sysreport_warn "$label installed but not active ($unit)"
|
|
17
|
+
fi
|
|
18
|
+
else
|
|
19
|
+
sysreport_unknown "$label not detected ($unit)"
|
|
20
|
+
fi
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
report_services() {
|
|
24
|
+
sysreport_section "Core Services"
|
|
25
|
+
|
|
26
|
+
report_service_status "OpenSSH" "sshd.service"
|
|
27
|
+
report_service_status "Nginx" "nginx.service"
|
|
28
|
+
report_service_status "Apache httpd" "httpd.service"
|
|
29
|
+
report_service_status "Apache apache2" "apache2.service"
|
|
30
|
+
report_service_status "MariaDB" "mariadb.service"
|
|
31
|
+
report_service_status "MySQL" "mysql.service"
|
|
32
|
+
report_service_status "PostgreSQL" "postgresql.service"
|
|
33
|
+
report_service_status "Redis" "redis.service"
|
|
34
|
+
report_service_status "Memcached" "memcached.service"
|
|
35
|
+
report_service_status "Docker" "docker.service"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
sysreport_register_section "services" "Core service status" "report_services"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_webstack() {
|
|
4
|
+
local apache_version nginx_version php_version cpanel_version accounts suspended fpm_services disabled_functions
|
|
5
|
+
|
|
6
|
+
sysreport_section "Web Stack"
|
|
7
|
+
|
|
8
|
+
if sysreport_have httpd; then
|
|
9
|
+
apache_version="$(httpd -v 2>/dev/null | awk 'NR==1 {print $3}')"
|
|
10
|
+
sysreport_item "Apache" "${apache_version:-detected}"
|
|
11
|
+
elif sysreport_have apache2; then
|
|
12
|
+
apache_version="$(apache2 -v 2>/dev/null | awk 'NR==1 {print $3}')"
|
|
13
|
+
sysreport_item "Apache" "${apache_version:-detected}"
|
|
14
|
+
else
|
|
15
|
+
sysreport_item "Apache" "not detected"
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
if sysreport_have nginx; then
|
|
19
|
+
nginx_version="$(nginx -v 2>&1 | sed 's/^nginx version: //')"
|
|
20
|
+
sysreport_item "Nginx" "${nginx_version:-detected}"
|
|
21
|
+
else
|
|
22
|
+
sysreport_item "Nginx" "not detected"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if pgrep -af 'litespeed|lshttpd' >/dev/null 2>&1; then
|
|
26
|
+
sysreport_item "LiteSpeed" "running"
|
|
27
|
+
else
|
|
28
|
+
sysreport_item "LiteSpeed" "not detected"
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
if sysreport_have php; then
|
|
32
|
+
php_version="$(php -v 2>/dev/null | awk 'NR==1 {print $1 " " $2}')"
|
|
33
|
+
disabled_functions="$(php -r 'echo ini_get("disable_functions");' 2>/dev/null || true)"
|
|
34
|
+
sysreport_item "PHP CLI" "${php_version:-detected}"
|
|
35
|
+
sysreport_item "PHP OPcache" "$(php -v 2>/dev/null | grep -iq opcache && echo enabled || echo not detected)"
|
|
36
|
+
sysreport_item "PHP disable_functions" "${disabled_functions:-empty}"
|
|
37
|
+
else
|
|
38
|
+
sysreport_item "PHP CLI" "not detected"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
if sysreport_have systemctl; then
|
|
42
|
+
fpm_services="$(systemctl list-units --type=service --no-legend 2>/dev/null | awk '/php.*fpm|ea-php.*fpm/ {print $1 " " $4}' | head -n 20)"
|
|
43
|
+
sysreport_item "PHP-FPM units" ""
|
|
44
|
+
if [[ -n "$fpm_services" ]]; then
|
|
45
|
+
printf '%s\n' "$fpm_services" | awk '{print " " $1 ": " $2}'
|
|
46
|
+
else
|
|
47
|
+
sysreport_unknown "none detected"
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if [[ -x /usr/local/cpanel/cpanel ]]; then
|
|
52
|
+
cpanel_version="$(/usr/local/cpanel/cpanel -V 2>/dev/null || true)"
|
|
53
|
+
accounts="$(find /var/cpanel/users -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ')"
|
|
54
|
+
suspended="$(find /var/cpanel/suspended -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ')"
|
|
55
|
+
sysreport_item "cPanel/WHM" "version ${cpanel_version:-unknown}; accounts ${accounts:-0}; suspended ${suspended:-0}"
|
|
56
|
+
else
|
|
57
|
+
sysreport_item "cPanel/WHM" "not detected"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
sysreport_register_section "webstack" "Web, PHP, and cPanel profile" "report_webstack"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_database() {
|
|
4
|
+
local mysql_version slow_log buffer_pool pg_version
|
|
5
|
+
|
|
6
|
+
sysreport_section "Database"
|
|
7
|
+
|
|
8
|
+
if sysreport_have mysql; then
|
|
9
|
+
mysql_version="$(mysql -V 2>/dev/null)"
|
|
10
|
+
sysreport_item "MySQL client" "${mysql_version:-detected}"
|
|
11
|
+
|
|
12
|
+
slow_log="$(mysql --batch --skip-column-names -e "SHOW VARIABLES LIKE 'slow_query_log';" 2>/dev/null | awk '{print $2}' || true)"
|
|
13
|
+
sysreport_item "MySQL slow query log" "${slow_log:-unknown or access denied}"
|
|
14
|
+
|
|
15
|
+
buffer_pool="$(mysql --batch --skip-column-names -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" 2>/dev/null | awk '{printf "%.2f GB", $2/1024/1024/1024}' || true)"
|
|
16
|
+
sysreport_item "InnoDB buffer pool" "${buffer_pool:-unknown or access denied}"
|
|
17
|
+
else
|
|
18
|
+
sysreport_item "MySQL client" "not detected"
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
if sysreport_have psql; then
|
|
22
|
+
pg_version="$(psql --version 2>/dev/null)"
|
|
23
|
+
sysreport_item "PostgreSQL client" "${pg_version:-detected}"
|
|
24
|
+
else
|
|
25
|
+
sysreport_item "PostgreSQL client" "not detected"
|
|
26
|
+
fi
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
sysreport_register_section "database" "Database summary" "report_database"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_security_port() {
|
|
4
|
+
local port="$1" service
|
|
5
|
+
if sysreport_have ss && ss -H -tln 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]${port}$"; then
|
|
6
|
+
service="$(ss -H -tlnp 2>/dev/null | awk -v port="$port" '$4 ~ ":" port "$" {print $0; exit}' | sed 's/.*users:(("//; s/".*//')"
|
|
7
|
+
sysreport_ok "port $port open${service:+ ($service)}"
|
|
8
|
+
else
|
|
9
|
+
sysreport_warn "port $port closed or not visible"
|
|
10
|
+
fi
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
report_security_unit() {
|
|
14
|
+
local label="$1" unit="$2" status
|
|
15
|
+
|
|
16
|
+
if ! sysreport_have systemctl; then
|
|
17
|
+
return 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if ! systemctl list-unit-files --no-legend "$unit" 2>/dev/null | grep -q . && \
|
|
21
|
+
! systemctl list-units --no-legend "$unit" 2>/dev/null | grep -q .; then
|
|
22
|
+
return 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
status="$(systemctl is-active "$unit" 2>/dev/null || true)"
|
|
26
|
+
case "$status" in
|
|
27
|
+
active)
|
|
28
|
+
sysreport_ok "$label active ($unit)"
|
|
29
|
+
;;
|
|
30
|
+
failed)
|
|
31
|
+
sysreport_fail "$label installed but failed ($unit)"
|
|
32
|
+
;;
|
|
33
|
+
inactive|deactivating|activating)
|
|
34
|
+
sysreport_warn "$label installed but $status ($unit)"
|
|
35
|
+
;;
|
|
36
|
+
*)
|
|
37
|
+
sysreport_warn "$label installed but status is ${status:-unknown} ($unit)"
|
|
38
|
+
;;
|
|
39
|
+
esac
|
|
40
|
+
|
|
41
|
+
return 0
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
report_security() {
|
|
45
|
+
local ssh_config ssh_port root_login password_auth found_security_unit
|
|
46
|
+
|
|
47
|
+
sysreport_section "Security"
|
|
48
|
+
|
|
49
|
+
ssh_config="/etc/ssh/sshd_config"
|
|
50
|
+
if [[ -r "$ssh_config" ]]; then
|
|
51
|
+
ssh_port="$(awk 'tolower($1)=="port" {print $2; exit}' "$ssh_config")"
|
|
52
|
+
root_login="$(awk 'tolower($1)=="permitrootlogin" {print $2; exit}' "$ssh_config")"
|
|
53
|
+
password_auth="$(awk 'tolower($1)=="passwordauthentication" {print $2; exit}' "$ssh_config")"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
sysreport_item "SSH port" "${ssh_port:-22}"
|
|
57
|
+
[[ "${ssh_port:-22}" == "22" ]] && sysreport_warn "SSH is using the default port 22" || sysreport_ok "SSH port is customized"
|
|
58
|
+
sysreport_item "SSH root login" "${root_login:-default}"
|
|
59
|
+
[[ "${root_login:-}" == "yes" ]] && sysreport_warn "PermitRootLogin is enabled" || sysreport_ok "PermitRootLogin is not explicitly enabled"
|
|
60
|
+
sysreport_item "SSH password auth" "${password_auth:-default}"
|
|
61
|
+
|
|
62
|
+
printf '\n'
|
|
63
|
+
sysreport_item "Firewall and hardening services" ""
|
|
64
|
+
found_security_unit=0
|
|
65
|
+
report_security_unit "CSF firewall" "csf.service" && found_security_unit=1
|
|
66
|
+
report_security_unit "LFD login failure daemon" "lfd.service" && found_security_unit=1
|
|
67
|
+
report_security_unit "Imunify360" "imunify360.service" && found_security_unit=1
|
|
68
|
+
report_security_unit "firewalld" "firewalld.service" && found_security_unit=1
|
|
69
|
+
report_security_unit "ufw" "ufw.service" && found_security_unit=1
|
|
70
|
+
[[ "$found_security_unit" -eq 0 ]] && sysreport_unknown "no common firewall or hardening service detected"
|
|
71
|
+
|
|
72
|
+
if sysreport_have fail2ban-client; then
|
|
73
|
+
sysreport_item "Fail2ban" "$(fail2ban-client ping 2>/dev/null | tr '\n' ' ' || echo detected)"
|
|
74
|
+
else
|
|
75
|
+
sysreport_item "Fail2ban" "not detected"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
printf '\n'
|
|
79
|
+
sysreport_item "Common exposed ports" ""
|
|
80
|
+
for port in 22 80 443 3306 5432 6379 8080 2083 2087; do
|
|
81
|
+
report_security_port "$port"
|
|
82
|
+
done
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
sysreport_register_section "security" "Security posture" "report_security"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
report_optimization() {
|
|
4
|
+
local disk_usage load_one cpu_cores swap_used disabled_funcs
|
|
5
|
+
|
|
6
|
+
sysreport_section "Optimization Checks"
|
|
7
|
+
|
|
8
|
+
disk_usage="$(df / 2>/dev/null | awk 'NR==2 {gsub("%","",$5); print $5}')"
|
|
9
|
+
if [[ -n "$disk_usage" && "$disk_usage" -ge 85 ]]; then
|
|
10
|
+
sysreport_fail "root disk usage is high (${disk_usage}%)"
|
|
11
|
+
elif [[ -n "$disk_usage" ]]; then
|
|
12
|
+
sysreport_ok "root disk usage is healthy (${disk_usage}%)"
|
|
13
|
+
else
|
|
14
|
+
sysreport_unknown "root disk usage unavailable"
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
load_one="$(uptime 2>/dev/null | awk -F'load average: ' '{print $2}' | cut -d, -f1 | tr -d ' ')"
|
|
18
|
+
cpu_cores="$(nproc 2>/dev/null || echo 1)"
|
|
19
|
+
if [[ -n "${load_one:-}" ]] && awk "BEGIN {exit !($load_one > $cpu_cores)}" 2>/dev/null; then
|
|
20
|
+
sysreport_warn "1-minute load (${load_one}) is above CPU cores (${cpu_cores})"
|
|
21
|
+
else
|
|
22
|
+
sysreport_ok "1-minute load (${load_one:-unknown}) is within CPU capacity (${cpu_cores})"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
swap_used="$(free -m 2>/dev/null | awk '/^Swap:/ {print $3}')"
|
|
26
|
+
if [[ -n "$swap_used" && "$swap_used" -gt 500 ]]; then
|
|
27
|
+
sysreport_warn "swap usage is above 500 MB (${swap_used} MB)"
|
|
28
|
+
elif [[ -n "$swap_used" ]]; then
|
|
29
|
+
sysreport_ok "swap usage is low (${swap_used} MB)"
|
|
30
|
+
else
|
|
31
|
+
sysreport_unknown "swap usage unavailable"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if pgrep -af 'redis-server|memcached' >/dev/null 2>&1; then
|
|
35
|
+
sysreport_ok "object cache service detected"
|
|
36
|
+
else
|
|
37
|
+
sysreport_warn "no Redis or Memcached process detected"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if sysreport_have php; then
|
|
41
|
+
disabled_funcs="$(php -r 'echo ini_get("disable_functions");' 2>/dev/null || true)"
|
|
42
|
+
if [[ -z "$disabled_funcs" ]]; then
|
|
43
|
+
sysreport_warn "PHP disable_functions is empty"
|
|
44
|
+
else
|
|
45
|
+
sysreport_ok "PHP disable_functions is configured"
|
|
46
|
+
fi
|
|
47
|
+
else
|
|
48
|
+
sysreport_unknown "PHP CLI not available for PHP hardening check"
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
sysreport_register_section "optimization" "Operational optimization checks" "report_optimization"
|