Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
13fe8a0
agents: use apt-get simulation for Ubuntu 18 compatibility; fix insta…
9technologygroup Sep 24, 2025
a9c579b
setup: fix IP address handling for database/service names
9technologygroup Sep 24, 2025
456184d
setup: improve sudo handling and add root checks
9technologygroup Sep 24, 2025
c3013cc
Added min specs of VM / LXC
9technologygroup Sep 24, 2025
9f3016b
deps: update all dependencies to latest non-deprecated versions
9technologygroup Sep 24, 2025
c4376d3
setup: add intelligent package manager detection for Debian 13+
9technologygroup Sep 24, 2025
78f4eff
fix: correct package versions and npm flags
9technologygroup Sep 24, 2025
a479003
fix: return first_name and last_name in setup-admin and signup responses
9technologygroup Sep 24, 2025
783f8d7
Replaced older dependancies with newer ones
9technologygroup Sep 25, 2025
b7ce2a3
docs(docker): move password update docs
tigattack Sep 24, 2025
03d6ebb
chore(compose): move `agent_files` to docker vol
tigattack Sep 24, 2025
38d0dcb
docs(docker): add volumes info
tigattack Sep 24, 2025
5f0ce7f
chore(docker): unpin alpine version
tigattack Sep 24, 2025
0cca660
chore(docker): tweak db healthcheck
tigattack Sep 24, 2025
6d70a67
docs(docker): link to images in GHCR
tigattack Sep 24, 2025
591389a
style(backend): fmt
tigattack Sep 24, 2025
b43b20f
style(frontend): fmt
tigattack Sep 24, 2025
330f804
chore: add biome
tigattack Sep 24, 2025
35bf858
fix(frontend): use `useId()` for input IDs
tigattack Sep 24, 2025
a11f180
fix(frontend): add missing explicit types for button elems
tigattack Sep 24, 2025
15902da
fix(frontend): use `useId()` for input IDs
tigattack Sep 24, 2025
83ce7c6
style(frontend): fmt
tigattack Sep 24, 2025
a84da7c
fix(frontend): Static Elements should not be interactive
tigattack Sep 24, 2025
74f42b5
fix(frontend): A form label must be associated with an input
tigattack Sep 24, 2025
53f8471
fix(frontend): Avoid using the index of an array as key property in a…
tigattack Sep 24, 2025
ce2ba0f
fix(frontend): hook does not specify its dependency
tigattack Sep 24, 2025
6e1ec0d
fix(frontend): elements with button role can be changed to button
tigattack Sep 24, 2025
a32007f
fix(frontend): Static Elements should not be interactive
tigattack Sep 24, 2025
67a5462
fix(frontend): imports are unused
tigattack Sep 24, 2025
a1bf2df
fix(frontend): unused vars/params
tigattack Sep 24, 2025
c840a3f
fix(frontend): isNaN is unsafe
tigattack Sep 24, 2025
6357839
fix(frontend): Change to an optional chain
tigattack Sep 25, 2025
0414ea3
fix(frontend): Use Date.now() instead of new Date()
tigattack Sep 25, 2025
42f6971
fix(frontend): variable unused
tigattack Sep 25, 2025
adc142f
fix(frontend): Missing radix parameter
tigattack Sep 25, 2025
047fdb4
fix(frontend): unused parameters
tigattack Sep 25, 2025
ea55025
fix(frontend): unused imports
tigattack Sep 25, 2025
3bdf3d1
ci: add code quality workflow
tigattack Sep 25, 2025
ffbf5f1
fix(frontend): add missing import
tigattack Sep 25, 2025
17509cb
fix(frontend): fix missing icons
tigattack Sep 25, 2025
03802da
fix(frontend): bad key
tigattack Sep 25, 2025
22f6bef
fix(backend): lint errors
tigattack Sep 25, 2025
469107c
fix: incorrect cardId
tigattack Sep 25, 2025
35eb930
style: fmt
tigattack Sep 25, 2025
3c01c4b
chore: add lefthook commit hook
tigattack Sep 25, 2025
641272d
Put in more env variables and fallback to localhost if BACKEND_URL an…
9technologygroup Sep 25, 2025
1ff3da0
fix(frontend): add missing `useId` imports
tigattack Sep 26, 2025
527b0cc
Fixed auto-update toggle to refresh upon save
9technologygroup Sep 26, 2025
eb3f359
Fixed group selection to be in effect when selecting the group upon h…
9technologygroup Sep 26, 2025
dbebb86
Removed formreturn data to be outputted in console log when host is c…
9technologygroup Sep 26, 2025
0c0446a
Added a few dashboard enhancements with Doughnut charts
9technologygroup Sep 26, 2025
e9bac06
Merge pull request #2 from 9technologygroup/iby-suggestions-for-pr-52
tigattack Sep 26, 2025
40a9003
Merge pull request #52 from tigattack/style/fmt
9technologygroup Sep 26, 2025
a76a722
Fixed inline toggle changes when viewing the list of hosts in table
9technologygroup Sep 26, 2025
71d9884
fix(frontend): imports are unused
tigattack Sep 24, 2025
e3aa28a
fix: login after signup
tigattack Sep 25, 2025
ba087eb
chore: add types/bcryptjs
tigattack Sep 25, 2025
5c66887
refactor(frontend): optimise auth process
tigattack Sep 25, 2025
60fa598
fix(frontend): solve missing imports
tigattack Sep 26, 2025
c4e0567
fix(frontend): use React Router navigation to open add host modal
tigattack Sep 26, 2025
d859206
Merge pull request #58 from tigattack/post_lint_fixes
9technologygroup Sep 26, 2025
be3fe52
fix(api): resolve duplicate key constraint errors in host package upd…
tigattack Sep 26, 2025
c886b81
chore: clarify auto-update feature
tigattack Sep 26, 2025
751a202
fix(frontend): actually fix login after signup
tigattack Sep 26, 2025
102546e
fix(frontend): eliminate duplicate API calls during log in/out
tigattack Sep 27, 2025
1750426
refactor(frontend): don't store permissions in localstorage
tigattack Sep 27, 2025
f99e01a
refactor(frontend): don't store current host tab in localstorage
tigattack Sep 27, 2025
df04770
Merge pull request #60 from tigattack/more_fixes
9technologygroup Sep 27, 2025
bed52a0
Merge remote-tracking branch 'origin/v1-2-7' into v1-2-7
9technologygroup Sep 28, 2025
edfd82a
Added --ignore-scripts to npm ci commands for lefthook script to not …
9technologygroup Sep 28, 2025
6adbbca
changed Docker flags to RUN npm ci --ignore-scripts && \
9technologygroup Sep 28, 2025
c18696f
Fixed syntax in npm commands
9technologygroup Sep 28, 2025
840664c
chore: fixup package-lock, remove unused deps
tigattack Sep 28, 2025
178f871
chore: remove unnecessary use of npx
tigattack Sep 28, 2025
40bf874
fix(frontend.dockerfile): remove unused line
tigattack Sep 28, 2025
3b72794
made the crontab installation safe as opposed to nuking it - spotted …
9technologygroup Sep 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/code_quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Code quality

on:
push:
pull_request:

jobs:
check:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
with:
persist-credentials: false

- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest

- name: Run Biome
run: biome ci .
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,4 @@ setup-installer-site.sh
install-server.*
notify-clients-upgrade.sh
debug-agent.sh
docker/agents
docker/compose_dev_data
35 changes: 30 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,30 @@ For getting started with Docker, see the [Docker documentation](https://github.c

Run on a clean Ubuntu/Debian server with internet access:

#### Debian:
```bash
apt update -y
apt upgrade -y
apt install curl -y
```

#### Ubuntu:
```bash
apt-get update -y
apt-get upgrade -y
apt install curl -y
```

#### Script
```bash
curl -fsSL -o setup.sh https://raw.githubusercontent.com/9technologygroup/patchmon.net/main/setup.sh && chmod +x setup.sh && bash setup.sh
```

#### Minimum specs for building : #####
CPU : 2 vCPU
RAM : 2GB
Disk : 15GB

During setup you’ll be asked:
- Domain/IP: public DNS or local IP (default: `patchmon.internal`)
- SSL/HTTPS: `y` for public deployments with a public IP, `n` for internal networks
Expand Down Expand Up @@ -157,14 +177,19 @@ We welcome contributions from the community! Here's how you can get involved:
git checkout -b fix/your-bug-fix
```

4. **Install Dependencies and Setup Hooks**
```bash
npm install
npm run prepare
```

4. **Make Your Changes**
5. **Make Your Changes**
- Write clean, well-documented code
- Follow existing code style and patterns
- Add tests for new functionality
- Update documentation as needed

5. **Test Your Changes**
6. **Test Your Changes**
```bash
# Run backend tests
cd backend
Expand All @@ -175,21 +200,21 @@ We welcome contributions from the community! Here's how you can get involved:
npm test
```

6. **Commit and Push**
7. **Commit and Push**
```bash
git add .
git commit -m "Add: descriptive commit message"
git push origin feature/your-feature-name
```

7. **Create a Pull Request**
8. **Create a Pull Request**
- Go to your fork on GitHub
- Click "New Pull Request"
- Provide a clear description of your changes
- Link any related issues

### Contribution Guidelines
- **Code Style**: Follow the existing code patterns and ESLint configuration
- **Code Style**: Follow the existing code patterns and Biome configuration
- **Commits**: Use conventional commit messages (feat:, fix:, docs:, etc.)
- **Testing**: Ensure all tests pass and add tests for new features
- **Documentation**: Update README and code comments as needed
Expand Down
33 changes: 18 additions & 15 deletions agents/patchmon-agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -550,33 +550,36 @@ get_apt_packages() {
local -n packages_ref=$1
local -n first_ref=$2

# Update package lists
# Update package lists (use apt-get for older distros; quieter output)
apt-get update -qq

# Get upgradable packages
local upgradable=$(apt list --upgradable 2>/dev/null | grep -v "WARNING")
# Determine upgradable packages using apt-get simulation (compatible with Ubuntu 18.04)
# Example line format:
# Inst bash [4.4.18-2ubuntu1] (4.4.18-2ubuntu1.2 Ubuntu:18.04/bionic-updates [amd64])
local upgradable_sim=$(apt-get -s -o Debug::NoLocking=1 upgrade 2>/dev/null | grep "^Inst ")

while IFS= read -r line; do
if [[ "$line" =~ ^([^/]+)/([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+.*[[:space:]]([^[:space:]]+)[[:space:]]*(\[.*\])? ]]; then
# Extract package name, current version (in brackets), and available version (first token inside parentheses)
if [[ "$line" =~ ^Inst[[:space:]]+([^[:space:]]+)[[:space:]]+\[([^\]]+)\][[:space:]]+\(([^[:space:]]+) ]]; then
local package_name="${BASH_REMATCH[1]}"
local current_version="${BASH_REMATCH[4]}"
local current_version="${BASH_REMATCH[2]}"
local available_version="${BASH_REMATCH[3]}"
local is_security_update=false

# Check if it's a security update
if echo "$line" | grep -q "security"; then
# Mark as security update if the line references a security pocket
if echo "$line" | grep -qiE "(-|/)security"; then
is_security_update=true
fi

if [[ "$first_ref" == true ]]; then
first_ref=false
else
packages_ref+=","
packages_ref+=","
fi

packages_ref+="{\"name\":\"$package_name\",\"currentVersion\":\"$current_version\",\"availableVersion\":\"$available_version\",\"needsUpdate\":true,\"isSecurityUpdate\":$is_security_update}"
fi
done <<< "$upgradable"
done <<< "$upgradable_sim"

# Get installed packages that are up to date
local installed=$(dpkg-query -W -f='${Package} ${Version}\n' | head -100)
Expand Down Expand Up @@ -818,7 +821,7 @@ EOF
success "Update sent successfully"
echo "$response" | grep -o '"packagesProcessed":[0-9]*' | cut -d':' -f2 | xargs -I {} info "Processed {} packages"

# Check for auto-update instructions (look specifically in autoUpdate section)
# Check for PatchMon agent update instructions (this updates the agent script, not system packages)
if echo "$response" | grep -q '"autoUpdate":{'; then
local auto_update_section=$(echo "$response" | grep -o '"autoUpdate":{[^}]*}')
local should_update=$(echo "$auto_update_section" | grep -o '"shouldUpdate":true' | cut -d':' -f2)
Expand All @@ -827,15 +830,15 @@ EOF
local current_version=$(echo "$auto_update_section" | grep -o '"currentVersion":"[^"]*' | cut -d'"' -f4)
local update_message=$(echo "$auto_update_section" | grep -o '"message":"[^"]*' | cut -d'"' -f4)

info "Auto-update detected: $update_message"
info "PatchMon agent update detected: $update_message"
info "Current version: $current_version, Latest version: $latest_version"

# Automatically run update-agent command
info "Automatically updating agent to latest version..."
# Automatically run update-agent command to update the PatchMon agent script
info "Automatically updating PatchMon agent to latest version..."
if "$0" update-agent; then
success "Agent auto-update completed successfully"
success "PatchMon agent update completed successfully"
else
warning "Agent auto-update failed, but data was sent successfully"
warning "PatchMon agent update failed, but data was sent successfully"
fi
fi
fi
Expand Down
26 changes: 18 additions & 8 deletions agents/patchmon_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,24 @@ else
warning "Initial package data failed, but agent is configured. You can run 'patchmon-agent.sh update' manually."
fi

# Setup crontab for automatic updates
info "⏰ Setting up automatic updates every $UPDATE_INTERVAL minutes..."
# Setup crontab for automatic package status updates
info "⏰ Setting up automatic package status update every $UPDATE_INTERVAL minutes..."

# Check if patchmon cron job already exists
PATCHMON_CRON_EXISTS=$(crontab -l 2>/dev/null | grep -c "patchmon-agent.sh update" || true)

if [[ $PATCHMON_CRON_EXISTS -gt 0 ]]; then
info " Existing PatchMon cron job found, removing old entry..."
# Remove existing patchmon cron entries and preserve other entries
(crontab -l 2>/dev/null | grep -v "patchmon-agent.sh update") | crontab -
fi

if [[ $UPDATE_INTERVAL -eq 60 ]]; then
# Hourly updates
echo "0 * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1" | crontab -
# Hourly updates - safely append to existing crontab
(crontab -l 2>/dev/null; echo "0 * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1") | crontab -
else
# Custom interval updates
echo "*/$UPDATE_INTERVAL * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1" | crontab -
# Custom interval updates - safely append to existing crontab
(crontab -l 2>/dev/null; echo "*/$UPDATE_INTERVAL * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1") | crontab -
fi

success "🎉 PatchMon Agent installation complete!"
Expand All @@ -179,8 +189,8 @@ if [[ "$EXPECTED_VERSION" != "Unknown" ]]; then
fi
echo " • Config directory: /etc/patchmon/"
echo " • Credentials file: /etc/patchmon/credentials"
echo " • Automatic updates: Every $UPDATE_INTERVAL minutes via crontab"
echo " • View logs: tail -f /var/log/patchmon-agent.sh"
echo " • Status updates: Every $UPDATE_INTERVAL minutes via crontab"
echo " • View logs: tail -f /var/log/patchmon-agent.log"
echo ""
echo "🔧 Manual commands:"
echo " • Test connection: patchmon-agent.sh test"
Expand Down
74 changes: 38 additions & 36 deletions backend/package.json
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
{
"name": "patchmon-backend",
"version": "1.2.6",
"description": "Backend API for Linux Patch Monitoring System",
"main": "src/server.js",
"scripts": {
"dev": "nodemon src/server.js",
"start": "node src/server.js",
"build": "echo 'No build step needed for Node.js'",
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev",
"db:push": "prisma db push",
"db:studio": "prisma studio"
},
"dependencies": {
"@prisma/client": "^5.7.0",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-rate-limit": "^7.1.5",
"express-validator": "^7.0.1",
"helmet": "^7.1.0",
"jsonwebtoken": "^9.0.2",
"moment": "^2.30.1",
"qrcode": "^1.5.4",
"speakeasy": "^2.0.0",
"uuid": "^9.0.1",
"winston": "^3.11.0"
},
"devDependencies": {
"nodemon": "^3.0.2",
"prisma": "^5.7.0"
},
"engines": {
"node": ">=18.0.0"
}
"name": "patchmon-backend",
"version": "1.2.6",
"description": "Backend API for Linux Patch Monitoring System",
"license": "AGPL-3.0",
"main": "src/server.js",
"scripts": {
"dev": "nodemon src/server.js",
"start": "node src/server.js",
"build": "echo 'No build step needed for Node.js'",
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev",
"db:push": "prisma db push",
"db:studio": "prisma studio"
},
"dependencies": {
"@prisma/client": "^6.1.0",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"express-validator": "^7.2.0",
"helmet": "^8.0.0",
"jsonwebtoken": "^9.0.2",
"moment": "^2.30.1",
"qrcode": "^1.5.4",
"speakeasy": "^2.0.0",
"uuid": "^11.0.3",
"winston": "^3.17.0"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.6",
"nodemon": "^3.1.9",
"prisma": "^6.1.0"
},
"engines": {
"node": ">=18.0.0"
}
}
Loading