Skip to content

slmingol/uptime-kuma-sync-n-bak

Repository files navigation

Uptime Kuma Sync & Backup

Uptime Kuma Sync Tool

Build and Push Container Version License: MIT Node.js Docker Container Registry Uptime Kuma

This tool synchronizes monitors and groups between two Uptime Kuma instances while preserving instance-specific settings.

Features

  • ✅ Syncs monitors (HTTP, TCP, Ping, etc.)
  • ✅ Syncs groups/tags with color coding
  • Syncs status pages - Groups, monitor membership, and page config replicated across instances
  • Shallow & Deep Sync Modes - Choose to preserve or copy instance-specific settings
  • ✅ Preserves instance-specific settings (intervals, timeouts, TTLs) in shallow mode
  • ✅ Updates existing monitors or creates new ones
  • ✅ Maps tags/groups correctly between instances
  • Parent/Group relationships - Correctly maintains monitor hierarchies
  • Tag associations - Uses dedicated addMonitorTag API for reliable tag syncing, prevents duplicates
  • Named instance configuration - Reference instances by name
  • Makefile - Convenient make targets for all common operations
  • Automatic backup before sync - Creates a timestamped backup of the target instance
  • Standalone backup tool - Backup any instance on demand
  • Restore tool - Restore from any backup file
  • Diff tool - Compare monitors between two instances
  • Incremental sync - Hash-based change detection skips unchanged monitors
  • Prune - Optionally delete target monitors absent from source (--prune)
  • Bidirectional sync - Copy target-only monitors back to source (--bidirectional)
  • Sync daemon - Scheduled sync service with a web status UI

Sync Modes

Shallow Mode (Default) sync primary secondary

Use when: You want to sync monitor definitions but keep each instance's own check intervals and notification settings.

What syncs:

  • Monitor names, types, URLs, hostnames
  • Basic configuration (auth, headers, accepted status codes, etc.)
  • Tags/groups (cleans duplicates, exact match from source)
  • Parent/group hierarchies
  • Status pages (groups, monitor membership, page config)

What stays on target:

  • Check intervals (interval, retryInterval, resendInterval)
  • Timeouts and retry limits (timeout, maxretries, maxredirects)
  • DNS resolution settings (dns_resolve_type, dns_resolve_server)
  • Notification settings (notificationIDList)

Example use case: Production→Staging sync where staging checks less frequently

Deep Mode sync primary secondary --deep

Use when: You want an exact replica of the source instance.

What syncs:

  • Everything from shallow mode, plus:
  • Check intervals and timing settings
  • Timeout and retry configuration
  • DNS resolution settings
  • Notification associations
  • All instance-specific settings

Example use case: DR (disaster recovery) setup, migrating to new instance

Tag & Hierarchy Handling (Both Modes)

Regardless of mode, sync now:

  1. Deletes all existing tags from target monitor
  2. Updates monitor configuration
  3. Adds fresh tags from source (prevents duplicates)
  4. Remaps parent/group relationships to maintain hierarchies

This prevents tag duplication and ensures hierarchies stay intact across instances with different IDs.

Installation

  1. Install required dependencies:
npm install axios socket.io-client dotenv
  1. Configure your instances:

Option A: Named Instances (Recommended)

Copy the example config and edit with your instance details:

cp uptime-kuma-config.json.example uptime-kuma-config.json

Edit uptime-kuma-config.json:

{
  "instances": {
    "primary": {
      "url": "https://uptime1.example.com",
      "username": "admin",
      "password": "your-password",
      "description": "Primary production instance"
    },
    "secondary": {
      "url": "https://uptime2.example.com",
      "username": "admin",
      "password": "your-password",
      "description": "Secondary backup instance"
    }
  },
  "backup": {
    "directory": "./uptime-kuma-backups"
  }
}

Option B: Environment Variables

Copy .env.uptime-kuma to .env.uptime-kuma.local and configure:

cp .env.uptime-kuma .env.uptime-kuma.local

Getting Started (Docker — No Clone Required)

No Node.js or git clone needed. Copy three files to any Docker host and run.

1. Create a deployment directory

mkdir uptime-kuma-sync && cd uptime-kuma-sync

2. Download the required files

curl -O https://raw.githubusercontent.com/slmingol/uptime-kuma-sync-n-bak/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/slmingol/uptime-kuma-sync-n-bak/main/Makefile
curl -O https://raw.githubusercontent.com/slmingol/uptime-kuma-sync-n-bak/main/uptime-kuma-config.json.example

3. Configure your instances

cp uptime-kuma-config.json.example uptime-kuma-config.json
# Edit uptime-kuma-config.json with your instance URLs and credentials

4. Start the sync daemon

make daemon

The daemon starts immediately, syncs primary → secondary, then repeats every 6 hours. Web UI available at http://<host>:8089.


Docker Installation (Dev / Full Repo)

Docker Commands Reference

./scripts/uptime-kuma-docker.sh list                                    # List configured instances
./scripts/uptime-kuma-docker.sh monitors <instance>                     # List monitors grouped by parent
./scripts/uptime-kuma-docker.sh monitors <instance> --tldr              # Monitor count by group and type
./scripts/uptime-kuma-docker.sh backup <instance>                       # Backup an instance
./scripts/uptime-kuma-docker.sh sync <source> <target>                  # Incremental shallow sync
./scripts/uptime-kuma-docker.sh sync <source> <target> --deep           # Sync with all settings
./scripts/uptime-kuma-docker.sh sync <source> <target> --force          # Full sync, ignore state
./scripts/uptime-kuma-docker.sh sync <source> <target> --prune          # Sync + delete target-only monitors
./scripts/uptime-kuma-docker.sh sync <source> <target> --prune --dry-run  # Preview prune without deleting
./scripts/uptime-kuma-docker.sh sync <source> <target> --bidirectional  # Sync both directions (source wins)
./scripts/uptime-kuma-docker.sh diff <source> <target>                  # Compare instances
./scripts/uptime-kuma-docker.sh diff <source> <target> --tldr           # Compare instances (summary)
./scripts/uptime-kuma-docker.sh restore <backup-file> [instance]        # Restore from backup
./scripts/uptime-kuma-docker.sh build                                   # Build the image
./scripts/uptime-kuma-docker.sh shell                                   # Interactive shell
./scripts/uptime-kuma-docker.sh help                                    # Show help

Makefile (Quickest Way to Run)

A Makefile wraps the Docker script for the most common operations. Run make help to see all targets.

make list                        # List configured instances
make monitors                    # List monitors in SOURCE grouped by parent
make monitors-tldr               # Monitor count by group and type for SOURCE
make sync                        # Incremental shallow sync SOURCE → TARGET
make sync-deep                   # Sync SOURCE → TARGET (deep, all settings)
make sync-force                  # Full sync SOURCE → TARGET (bypass state)
make sync-prune                  # Sync + delete target monitors absent from SOURCE
make sync-prune-dry              # Preview what sync-prune would delete
make sync-bidir                  # Bidirectional sync (source wins conflicts)
make diff                        # Diff SOURCE vs TARGET (full detail)
make diff-tldr                   # Diff SOURCE vs TARGET (summary)
make backup                      # Backup SOURCE instance
make restore FILE=<path>         # Restore backup to TARGET
make daemon                      # Start sync daemon + UI (port 8089)
make daemon-stop                 # Stop sync daemon
make daemon-logs                 # Follow daemon logs
make build                       # Build the Docker image locally
make shell                       # Drop into an interactive container shell

Override source/target instances:

make sync SOURCE=secondary TARGET=primary

Sync Daemon (Scheduled Sync + Web UI)

The daemon runs a sync on a configurable schedule and serves a status UI at port 8089.

# Start the daemon (pre-creates state files, then starts the Docker Compose service)
make daemon

# Stop the daemon
make daemon-stop

# Follow logs
make daemon-logs

The make daemon target is the correct way to start it — it runs touch on the host-side state files before Docker mounts them (Docker creates missing mount targets as directories, which breaks JSON parsing).

Configure via environment variables in your shell or a .env file:

Variable Default Description
SYNC_SOURCE primary Source instance name
SYNC_TARGET secondary Target instance name
SYNC_INTERVAL 21600 Seconds between syncs
SYNC_MODE shallow Sync mode (shallow or deep)
DAEMON_PORT 8089 Web UI port

The web UI at http://localhost:8089 shows sync status, countdown to next sync, a "Sync Now" button, and a history table of recent runs.

Docker Compose (Standalone Scheduled Backup)

The docker-compose.yml also includes a service for scheduled backups (separate from the daemon):

docker compose -f docker/docker-compose.yml up -d uptime-kuma-backup-cron

To run one-off commands:

docker compose -f docker/docker-compose.yml run --rm uptime-kuma-sync node src/uptime-kuma-backup.js primary
docker compose -f docker/docker-compose.yml run --rm uptime-kuma-sync node src/uptime-kuma-sync.js primary secondary
docker compose -f docker/docker-compose.yml run --rm uptime-kuma-sync node src/uptime-kuma-diff.js primary secondary

Manual Docker Run

If you prefer direct docker run commands:

# Build image
docker build -t uptime-kuma-sync:latest .

# Run backup
docker run --rm \
  -v "$(pwd)/uptime-kuma-config.json:/app/uptime-kuma-config.json:ro" \
  -v "$(pwd)/uptime-kuma-backups:/app/uptime-kuma-backups" \
  uptime-kuma-sync:latest node src/uptime-kuma-backup.js primary

# Run sync
docker run --rm \
  -v "$(pwd)/uptime-kuma-config.json:/app/uptime-kuma-config.json:ro" \
  -v "$(pwd)/uptime-kuma-backups:/app/uptime-kuma-backups" \
  uptime-kuma-sync:latest node src/uptime-kuma-sync.js primary secondary

Usage

Sync with Named Instances (Recommended)

The easiest way to sync - just reference your instances by name:

# Sync from primary to secondary
./scripts/sync-uptime.sh primary secondary

# Or run directly:
node src/uptime-kuma-sync.js primary secondary

Output example:

=== Creating Backup ===
Creating backup: uptime-kuma-backups/secondary-2026-03-01T15-30-00.json
Backup saved: 25 monitors, 5 tags
✓ Backup complete

=== Starting Sync ===
From: primary (https://uptime1.example.com)
To: secondary (https://uptime2.example.com)
...

Backups are automatically named based on the instance name!

Sync with Environment Variables

Using .env file:

./scripts/sync-uptime.sh

Or use environment variables directly:

SOURCE_UPTIME_URL=http://localhost:3001 \
SOURCE_UPTIME_USER=admin \
SOURCE_UPTIME_PASS=password1 \
SOURCE_NAME=primary \
TARGET_UPTIME_URL=http://localhost:3002 \
TARGET_UPTIME_USER=admin \
TARGET_UPTIME_PASS=password2 \
TARGET_NAME=secondary \
node src/uptime-kuma-sync.js

Sync Modes

The sync tool supports two modes to fit different use cases:

Shallow Sync (Default)

Best for: Maintaining independent instances with different monitoring configurations

Shallow sync copies monitor definitions while preserving instance-specific settings on the target:

# Shallow sync - preserves target's check intervals and timeouts
./scripts/sync-uptime.sh primary secondary
node src/uptime-kuma-sync.js primary secondary

What gets synced:

  • Monitor names and types
  • URLs, hostnames, and ports
  • Descriptions and keywords
  • Accepted status codes
  • Tags/groups (with colors)
  • Headers, body, method
  • Authentication settings
  • Certificate settings
  • Status pages (groups, monitor membership, page config)

What is preserved on the target:

  • Check intervals
  • Retry intervals
  • Timeout values
  • Max retries
  • Notification settings
  • DNS settings

Use cases:

  • Syncing monitors to a backup instance with different check frequencies
  • Maintaining a test environment with slower polling
  • Keeping notification settings separate per instance

Deep Sync

Best for: Creating exact replicas or clones

Deep sync copies everything from source to target, including all instance-specific settings:

# Deep sync - copies ALL settings including intervals
./scripts/sync-uptime.sh primary secondary --deep
node src/uptime-kuma-sync.js primary secondary --deep

What gets synced:

  • Everything from shallow mode PLUS:
  • Check intervals
  • Retry intervals
  • Timeout values
  • Max retries
  • Notification settings
  • DNS settings
  • Accepted status codes
  • All other configuration fields

Use cases:

  • Creating an exact replica/clone of an instance
  • Disaster recovery setup
  • Migrating to a new instance
  • Setting up identical production/staging environments

Setting Default Mode

You can set the default mode in your config file:

{
  "sync": {
    "mode": "deep"
  }
}

Override the default with command-line flags:

# Force shallow sync even if config says deep
./scripts/sync-uptime.sh primary secondary --shallow

# Force deep sync even if config says shallow  
./scripts/sync-uptime.sh primary secondary --deep

Manual Backup

Backup any instance by name:

# Backup named instance from config
node src/uptime-kuma-backup.js primary

# Creates: uptime-kuma-backups/primary-2026-03-01T15-30-00.json

Or with environment variables:

UPTIME_URL=https://uptime.example.com \
UPTIME_USER=admin \
UPTIME_PASS=password \
node src/uptime-kuma-backup.js production

Restore from Backup

Restore to a named instance:

node src/uptime-kuma-restore.js uptime-kuma-backups/primary-2026-03-01.json secondary

Or with environment variables:

TARGET_UPTIME_URL=https://uptime.example.com \
TARGET_UPTIME_USER=admin \
TARGET_UPTIME_PASS=password \
node src/uptime-kuma-restore.js uptime-kuma-backups/backup.json

Note: Restoring will ADD monitors from the backup. It won't delete existing monitors.

Compare Instances (Diff)

Compare monitors between two instances to see what's different:

# Using bash wrapper
./scripts/diff-uptime.sh primary secondary

# Or run directly
node src/uptime-kuma-diff.js primary secondary

# Or with npm
npm run diff primary secondary

# Show condensed summary (TL;DR mode)
./scripts/diff-uptime.sh primary secondary --tldr
node src/uptime-kuma-diff.js primary secondary --tldr

The diff tool shows:

  • Identical monitors - Monitors that match completely
  • Different monitors - Monitors with the same name but different settings
  • Only in source - Monitors that exist only in the first instance
  • Only in target - Monitors that exist only in the second instance

TL;DR Mode: Use --tldr flag to show a condensed summary with just monitor names and the most common differences, perfect for a quick overview.

Output Example:

Comparing monitors from primary to secondary...
Fetched 201 monitors from primary
Fetched 202 monitors from secondary

=== Summary ===
Identical monitors: 160
Different monitors: 41
Only in primary: 0
Only in secondary: 1

--- Monitors with differences (41) ---
  • Core Svcs [group] - 1 field(s) different
  • DNS - bubs.us.to [dns] - 1 field(s) different
  • WEB - Bandle [http] - 2 field(s) different
  ...

--- Most common differences ---
  • tags: 31 monitor(s)
  • childrenIDs: 9 monitor(s)
  • pathName: 9 monitor(s)

Or for full detail (without --tldr):

=== Differences ===
Monitor: Disk Usage
  childrenIDs: [147,146,145] → [224,223,222]
...

See README.diff.md for detailed documentation.

Docker Usage:

# Using docker-compose
docker-compose run --rm uptime-kuma-sync ./scripts/diff-uptime.sh primary secondary
docker-compose run --rm uptime-kuma-sync ./scripts/diff-uptime.sh primary secondary --tldr

# Using Docker wrapper script
./scripts/uptime-kuma-docker.sh diff primary secondary
./scripts/uptime-kuma-docker.sh diff primary secondary --tldr

Using Diff to Determine Sync Direction

The sync tool is bi-directional and safe - you can sync in either direction with automatic backups. Use the diff tool to determine which instance has the correct configuration:

Safety Features:

  • ✅ Automatic backup of target instance before sync
  • ✅ Non-destructive - updates existing monitors and creates missing ones (doesn't delete)
  • ✅ Preserves instance-specific settings (intervals, timeouts, notifications)

Workflow to Get Instances In Sync:

# 1. Compare both directions to see what's different
./scripts/diff-uptime.sh primary secondary --tldr
./scripts/diff-uptime.sh secondary primary --tldr

# 2. Identify your "source of truth" (the instance with correct data)
#    - Which has the correct tags/groups?
#    - Which has the correct monitor configurations?
#    - Which has the latest changes you want to keep?

# 3. Sync FROM your source of truth TO the other instance
./scripts/sync-uptime.sh <correct-instance> <target-instance>

# 4. Verify instances are now in sync
./scripts/diff-uptime.sh primary secondary --tldr

Example Scenario:

Your diff shows secondary has 1 extra monitor and different tags on 31 monitors:

# Check what secondary would change in primary
./scripts/diff-uptime.sh secondary primary --tldr

# If secondary has the correct tags, sync it to primary
./scripts/sync-uptime.sh secondary primary

# Or if primary is correct, sync the other direction
./scripts/sync-uptime.sh primary secondary

Backup Location: The tool creates timestamped backups in uptime-kuma-backups/ before each sync. You can restore if needed:

./scripts/restore-uptime.sh uptime-kuma-backups/primary-2026-03-01T15-30-00.json primary

Automated Sync

Set up a cron job to run periodically:

# Run every hour - sync from primary to secondary
0 * * * * cd /path/to/project && ./scripts/sync-uptime.sh primary secondary >> /var/log/uptime-sync.log 2>&1

# Daily backup of production instance
0 2 * * * cd /path/to/project && node src/uptime-kuma-backup.js production >> /var/log/uptime-backup.log 2>&1

Configuration Files

uptime-kuma-config.json

Define all your instances in one place:

{
  "instances": {
    "production": {
      "url": "https://uptime-prod.example.com",
      "username": "admin",
      "password": "prod-password",
      "description": "Production monitoring"
    },
    "staging": {
      "url": "https://uptime-staging.example.com",
      "username": "admin",
      "password": "staging-password",
      "description": "Staging environment"
    },
    "local": {
      "url": "http://localhost:3001",
      "username": "admin",
      "password": "admin",
      "description": "Local development"
    }
  },
  "backup": {
    "directory": "./uptime-kuma-backups"
  },
  "sync": {
    "mode": "shallow",
    "excludedFields": [
      "interval",
      "retryInterval",
      "resendInterval",
      "maxretries",
      "timeout",
      "upside_down",
      "maxredirects",
      "dns_resolve_type",
      "dns_resolve_server",
      "notificationIDList"
    ]
  }
}

Sync Mode:

  • "mode": "shallow" (default) - Preserves instance-specific settings on target
  • "mode": "deep" - Copies all settings for an exact replica
  • Can be overridden with --deep or --shallow flags

Benefits:

  • Define once, use everywhere
  • Automatic backup naming based on instance
  • Easy to manage multiple instances
  • No need to remember URLs and credentials
  • Version control friendly (add to .gitignore)

Instance Name Examples

Choose meaningful names for your instances:

  • production / backup
  • primary / secondary
  • datacenter1 / datacenter2
  • aws / azure
  • main / failover

These names appear in:

  • Backup filenames
  • Sync console output
  • Log files

What Gets Synced

Note: The fields below apply to Shallow Sync mode (default). For Deep Sync mode, ALL fields are copied including instance-specific settings. See the Sync Modes section for details.

Synced Fields (Shallow Mode)

  • Monitor name
  • Monitor type (HTTP, TCP, Ping, etc.)
  • URL/hostname
  • Port
  • Description
  • Accepted status codes
  • Tags/groups (with colors)
  • Headers
  • Body
  • Method
  • Authentication settings
  • Certificate settings
  • Keywords
  • Status pages (groups, monitor membership, page config)

NOT Synced in Shallow Mode (Instance-Specific)

  • Check interval
  • Retry interval
  • Resend interval
  • Max retries
  • Timeout
  • Status inversion (upside down)
  • Max redirects
  • DNS settings
  • Notification settings

In Deep Sync Mode: All the above instance-specific fields ARE synced for an exact replica.

Customization

Exclude Additional Fields

Edit uptime-kuma-config.json to customize which fields are excluded:

{
  "sync": {
    "excludedFields": [
      "interval",
      "your_custom_field"
    ]
  }
}

Include More Fields

Remove fields from the excludedFields array to sync them between instances.

Backup Management

Backup Files

Backups are JSON files containing:

  • All monitors with complete configuration
  • All tags/groups with colors
  • All status pages (config, groups, and monitor membership)
  • Timestamp and instance information

Backup Naming

When using named instances, backups are automatically named:

  • Format: {instance-name}-{timestamp}.json
  • Example: primary-2026-03-01T10-30-00.json

This makes it easy to identify which instance a backup is from!

Backup Location

Default: ./uptime-kuma-backups/

Configure in uptime-kuma-config.json:

{
  "backup": {
    "directory": "/path/to/backups"
  }
}

Or with environment variable:

export BACKUP_DIR=/path/to/backups

Cleaning Old Backups

# Keep last 30 days
find uptime-kuma-backups/ -name "*.json" -mtime +30 -delete

# Keep last 10 backups per instance
for instance in primary secondary; do
  ls -t uptime-kuma-backups/${instance}-*.json | tail -n +11 | xargs rm -f
done

Emergency Recovery

If a sync goes wrong, restore from the automatic backup:

# Find the latest backup
ls -lt uptime-kuma-backups/

# Restore to the named instance
node src/uptime-kuma-restore.js uptime-kuma-backups/secondary-2026-03-01T15-30-00.json secondary

Workflow

  1. Initial Setup: Configure both instances with their desired intervals, timeouts, and notification settings
  2. Add Monitors: Add monitors to your "source" instance with appropriate tags/groups
  3. Run Sync: Execute sync with instance names: ./scripts/sync-uptime.sh primary secondary
  4. Verify: Check target instance - monitors should be there with target's existing timing settings
  5. Regular Syncs: Schedule periodic syncs to keep monitors in sync

Troubleshooting

Connection Issues

  • Verify both instances are accessible
  • Check firewall rules
  • Ensure correct URLs (include http:// or https://)

Authentication Errors

  • Verify username and password in config
  • Check if 2FA is enabled (not supported)
  • Ensure the user has admin privileges

Tag/Group Mismatches

  • Tags are matched by name AND color
  • If colors differ, new tags will be created
  • Manually merge tags in the target instance if needed

Instance Not Found Error

Error: Instance 'xyz' not found in uptime-kuma-config.json
Available instances: primary, secondary, local
  • Check spelling of instance name
  • Verify instance exists in config file
  • List available instances: cat uptime-kuma-config.json | jq '.instances | keys'

Bidirectional Sync

Use the --bidirectional flag (or make sync-bidir) to sync monitors in both directions in a single run:

# Sync primary → secondary, then copy secondary-only monitors back to primary
make sync-bidir

# Or directly:
./scripts/uptime-kuma-docker.sh sync primary secondary --bidirectional

Conflict resolution: Source always wins. If a monitor exists on both instances, the source version is authoritative. The bidirectional pass only copies monitors that exist exclusively on the target back to the source.

Mutually exclusive with --prune — you can't prune and bidirectional-sync in the same run.

Scripts Overview

Core Node.js Scripts

  • uptime-kuma-sync.js - Sync monitors between two instances (auto-backup, incremental, prune, bidirectional)
  • uptime-kuma-backup.js - Standalone backup tool for any instance
  • uptime-kuma-restore.js - Restore monitors from a backup file
  • uptime-kuma-list.js - List monitors in an instance grouped by parent group
  • uptime-kuma-diff.js - Compare monitors between two instances
  • uptime-kuma-daemon.js - Scheduled sync daemon with web status UI (run via make daemon)

Bash Wrapper Scripts

  • sync-uptime.sh - Convenience wrapper for syncing
  • backup-uptime.sh - Convenience wrapper for backups
  • restore-uptime.sh - Convenience wrapper for restoring
  • diff-uptime.sh - Convenience wrapper for diffing instances

Docker Scripts

  • uptime-kuma-docker.sh - All-in-one Docker wrapper (recommended)
  • Dockerfile - Container definition
  • docker-compose.yml - For scheduled backups and easy deployment

Configuration Files

  • uptime-kuma-config.json - Instance configuration (create from .example file)
  • uptime-kuma-config.json.example - Template configuration file
  • .env.uptime-kuma - Environment variable template (optional)

Notes

  • The script uses Socket.IO to communicate with Uptime Kuma
  • Monitors are matched by name + type
  • Existing monitors are updated, new ones are created
  • Deleted monitors in source are NOT deleted in target by default — use --prune to remove them
  • Incremental sync skips monitors whose hash hasn't changed; use --force to bypass
  • Automatic backups are created before every sync - No data loss risk!
  • Instance names in config make it easy to manage multiple environments

API Reference

Uptime Kuma uses Socket.IO events:

  • login - Authenticate
  • getMonitorList - Get all monitors
  • getMonitor - Get monitor details
  • getTags - Get all tags
  • addTag - Create tag
  • add - Create monitor
  • editMonitor - Update monitor

About

Sync monitors and groups between multiple Uptime Kuma instances with automatic backup and restore functionality

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages