netbird-install-update: add install/update script with remote deployment and auto-update timers
- Detects Netbird installation method (binary vs package manager) - Replaces package manager installs with binary for consistency - Supports single-host and multi-host SSH deployment - Adds systemd timer for daily auto-updates with persistent scheduling - Handles sudo password automation via --password flag or hosts file - Connection-safe updates using background execution to survive SSH disconnects - Fixes SELinux contexts and binary permissions automatically - Provides detailed deployment summaries with per-host action tracking - Includes SSH timeout handling to prevent hanging on unreachable hosts - Color-coded output with icons for better readability
This commit is contained in:
@@ -11,6 +11,7 @@ A collection of utility scripts for Linux desktop and server administration.
|
|||||||
| [`docker-stacks-backup/`](docker-stacks-backup/) | Backup & restore Docker Compose stacks — named volumes, bind mounts, pre/post hooks, retention, integrity verification |
|
| [`docker-stacks-backup/`](docker-stacks-backup/) | Backup & restore Docker Compose stacks — named volumes, bind mounts, pre/post hooks, retention, integrity verification |
|
||||||
| [`docker-stacks-update/`](docker-stacks-update/) | Discover running Compose stacks, pull latest images, and restart only those that changed |
|
| [`docker-stacks-update/`](docker-stacks-update/) | Discover running Compose stacks, pull latest images, and restart only those that changed |
|
||||||
| [`input-remapper-switcher/`](input-remapper-switcher/) | Auto-switch [input-remapper](https://github.com/sezanzeb/input-remapper) presets per-application via Hyprland socket events |
|
| [`input-remapper-switcher/`](input-remapper-switcher/) | Auto-switch [input-remapper](https://github.com/sezanzeb/input-remapper) presets per-application via Hyprland socket events |
|
||||||
|
| [`netbird-install-update/`](netbird-install-update/) | Install, update, and manage Netbird across single or multiple Linux hosts — detects install method, replaces package-manager installs with binary, supports SSH remote deployment, auto-update timers, and sudo password automation |
|
||||||
| [`proxmox-backup/`](proxmox-backup/) | Backup & restore Proxmox VE configuration (local or over SSH) with integrity verification |
|
| [`proxmox-backup/`](proxmox-backup/) | Backup & restore Proxmox VE configuration (local or over SSH) with integrity verification |
|
||||||
| [`proxmox-cloudimg/`](proxmox-cloudimg/) | Download, customize, and create Proxmox VE VM templates from official cloud images |
|
| [`proxmox-cloudimg/`](proxmox-cloudimg/) | Download, customize, and create Proxmox VE VM templates from official cloud images |
|
||||||
| [`zsh/`](zsh/) | Zsh configuration (`.zshrc`), dependency bootstrap installer, and themed tmux config |
|
| [`zsh/`](zsh/) | Zsh configuration (`.zshrc`), dependency bootstrap installer, and themed tmux config |
|
||||||
|
|||||||
@@ -0,0 +1,444 @@
|
|||||||
|
# Netbird Install/Update Script
|
||||||
|
|
||||||
|
A comprehensive bash script for installing, updating, and managing Netbird across Linux systems. Supports local execution, single-host remote deployment, and multi-host fleet management.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Smart Installation**: Automatically detects and handles different Netbird installation methods
|
||||||
|
- **Package Manager Replacement**: Converts package manager installations to binary installs for better control
|
||||||
|
- **Connection-Safe Updates**: Background update process survives SSH disconnections during Netbird service restarts
|
||||||
|
- **Auto-Update Timer**: Systemd timer for daily automatic updates with persistent scheduling
|
||||||
|
- **Remote Deployment**: Deploy to single hosts or entire fleets via SSH with timeout handling
|
||||||
|
- **Detailed Summary**: Multi-host deployments show which hosts succeeded/failed and what action was performed
|
||||||
|
- **SELinux Compatible**: Automatically fixes SELinux contexts on RHEL/Fedora systems
|
||||||
|
- **No Artifacts**: Clean execution with no leftover files or logs
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Linux operating system
|
||||||
|
- Root/sudo access
|
||||||
|
- curl
|
||||||
|
- SSH client (for remote deployment)
|
||||||
|
- Internet connection to download Netbird
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Make the script executable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x netbird-install-update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Local Execution
|
||||||
|
|
||||||
|
Install or update Netbird on the local machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Install with automatic daily updates:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --timer
|
||||||
|
```
|
||||||
|
|
||||||
|
Install with custom update schedule:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --timer --time "03:00"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Single Host Remote Deployment
|
||||||
|
|
||||||
|
Deploy to a remote host via SSH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --ssh user@hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy with sudo password (non-interactive):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --ssh user@hostname --password "your_sudo_password"
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy with auto-update timer enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --ssh user@hostname --timer
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy with custom update schedule:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --ssh user@hostname --timer --time "03:00"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multi-Host Fleet Deployment
|
||||||
|
|
||||||
|
Deploy to multiple hosts using a hosts file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --file hosts.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy with default sudo password for all hosts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --file hosts.txt --password "your_sudo_password"
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy with auto-update timer to all hosts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --file hosts.txt --timer
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy with custom update schedule to all hosts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh --file hosts.txt --timer --time "03:00"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Hosts File Format
|
||||||
|
|
||||||
|
Create a text file with one hostname or IP address per line. Empty lines and comments (starting with `#`) are ignored.
|
||||||
|
|
||||||
|
**Optional: Include sudo password**
|
||||||
|
|
||||||
|
You can optionally include the sudo password after the hostname (separated by space). Host-specific passwords override the default password provided via `--password`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Production servers (with host-specific sudo passwords)
|
||||||
|
prod-web-01.example.com MySudoPassword123
|
||||||
|
prod-web-02.example.com MySudoPassword456
|
||||||
|
prod-db-01.example.com MySudoPassword789
|
||||||
|
|
||||||
|
# Development servers (will use default password from --password flag)
|
||||||
|
dev-app-01.example.com
|
||||||
|
dev-app-02.example.com
|
||||||
|
|
||||||
|
# IP addresses also work
|
||||||
|
192.168.1.100
|
||||||
|
10.0.0.50 MyPassword
|
||||||
|
```
|
||||||
|
|
||||||
|
**Password Precedence**:
|
||||||
|
1. Host-specific password in hosts file (highest priority)
|
||||||
|
2. Default password from `--password` flag
|
||||||
|
3. Interactive sudo prompt (if no password provided)
|
||||||
|
|
||||||
|
**Security Warning**: Storing passwords in plain text is not recommended for production environments. Consider using SSH key authentication with passwordless sudo instead.
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- If a password is provided (via hosts file or `--password` flag), `sshpass` must be installed on the local machine
|
||||||
|
- If no password is provided, you'll be prompted to enter the sudo password interactively for each host
|
||||||
|
|
||||||
|
See `hosts.example` for a template.
|
||||||
|
|
||||||
|
## Command-Line Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--ssh <host>` | Deploy to a single remote host via SSH |
|
||||||
|
| `--file <path>` | Deploy to multiple hosts listed in a file |
|
||||||
|
| `--hosts-file <path>` | Alias for `--file` |
|
||||||
|
| `--timer` | Install systemd timer for auto-updates |
|
||||||
|
| `--time <schedule>` | Set update schedule (default: "daily") |
|
||||||
|
| `--password, -p <password>` | Default sudo password for remote hosts |
|
||||||
|
|
||||||
|
The `--time` option accepts systemd calendar event format. Examples:
|
||||||
|
- `daily` - Run once per day at midnight (default)
|
||||||
|
- `03:00` - Run at 3:00 AM daily
|
||||||
|
- `Mon,Fri 02:30` - Run at 2:30 AM on Monday and Friday
|
||||||
|
- `hourly` - Run every hour
|
||||||
|
- `weekly` - Run once per week
|
||||||
|
|
||||||
|
The `--password` option provides a default sudo password for remote deployments. This can be overridden per-host in the hosts file.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
### Installation Detection
|
||||||
|
|
||||||
|
The script detects three installation states:
|
||||||
|
|
||||||
|
1. **Not Installed**: Netbird binary not found in PATH
|
||||||
|
2. **Package Manager Install**: Installed via apt, yum, dnf, zypper, or rpm-ostree
|
||||||
|
3. **Binary Install**: Installed via the official curl-based installer
|
||||||
|
|
||||||
|
Detection is performed by:
|
||||||
|
- Checking `/etc/netbird/install.conf` (authoritative source)
|
||||||
|
- Querying package managers (dpkg, rpm)
|
||||||
|
- Falling back to binary install detection
|
||||||
|
|
||||||
|
### Installation Flow
|
||||||
|
|
||||||
|
**Fresh Installation (Not Installed)**:
|
||||||
|
1. Downloads official Netbird install script
|
||||||
|
2. Runs binary-only installation (no GUI, no package manager)
|
||||||
|
3. Ensures proper ownership and permissions
|
||||||
|
4. Fixes SELinux contexts if applicable
|
||||||
|
|
||||||
|
**Package Manager Replacement**:
|
||||||
|
1. Downloads official Netbird install script
|
||||||
|
2. Schedules background replacement (3-second delay)
|
||||||
|
3. Stops Netbird service
|
||||||
|
4. Removes package manager installation
|
||||||
|
5. Runs binary installation
|
||||||
|
6. Ensures proper ownership, permissions, and SELinux contexts
|
||||||
|
|
||||||
|
**Binary Update**:
|
||||||
|
1. Compares current version with latest release
|
||||||
|
2. If outdated, schedules background update (3-second delay)
|
||||||
|
3. Runs official update process
|
||||||
|
4. Ensures proper ownership, permissions, and SELinux contexts
|
||||||
|
|
||||||
|
### Connection-Safe Updates
|
||||||
|
|
||||||
|
When updating over SSH, the script uses a detached background process to avoid disconnection issues:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
setsid bash -c 'sleep 3 && [update commands]' </dev/null >/var/log/netbird-update.log 2>&1 &
|
||||||
|
```
|
||||||
|
|
||||||
|
The 3-second delay allows the SSH session to complete cleanly before the Netbird service is stopped and restarted. The update continues even if your connection drops.
|
||||||
|
|
||||||
|
### Auto-Update Timer
|
||||||
|
|
||||||
|
When `--timer` is specified, the script creates a systemd timer that:
|
||||||
|
|
||||||
|
- Runs on a configurable schedule (default: daily at midnight with random 0-10 minute delay)
|
||||||
|
- Uses `Persistent=true` to catch up on missed runs after system boot
|
||||||
|
- Logs output to `/var/log/netbird-update.log`
|
||||||
|
- Automatically updates existing timers if already installed
|
||||||
|
|
||||||
|
The schedule can be customized with the `--time` option. Examples:
|
||||||
|
- `--time "daily"` - Run once per day at midnight (default)
|
||||||
|
- `--time "03:00"` - Run at 3:00 AM daily
|
||||||
|
- `--time "Mon,Fri 02:30"` - Run at 2:30 AM on Monday and Friday
|
||||||
|
- `--time "hourly"` - Run every hour
|
||||||
|
- `--time "weekly"` - Run once per week
|
||||||
|
|
||||||
|
The timer consists of two systemd units:
|
||||||
|
|
||||||
|
**netbird-update.service**:
|
||||||
|
```ini
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/bin/bash -c 'curl -fsSL https://pkgs.netbird.io/install.sh | UPDATE_NETBIRD=true sh && chown root:root /usr/bin/netbird 2>/dev/null || true && chmod +x /usr/bin/netbird 2>/dev/null || true && restorecon -v /usr/bin/netbird 2>/dev/null || true'
|
||||||
|
```
|
||||||
|
|
||||||
|
**netbird-update.timer**:
|
||||||
|
```ini
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=daily
|
||||||
|
Persistent=true
|
||||||
|
RandomizedDelaySec=600
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
All background operations log to `/var/log/netbird-update.log`:
|
||||||
|
|
||||||
|
- Package manager replacement operations
|
||||||
|
- In-place updates
|
||||||
|
- Systemd timer executions
|
||||||
|
|
||||||
|
Check the log to monitor update progress or troubleshoot issues:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tail -f /var/log/netbird-update.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Netbird Service Fails to Start
|
||||||
|
|
||||||
|
If the Netbird service fails with "Permission denied" errors:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check binary permissions
|
||||||
|
ls -la /usr/bin/netbird
|
||||||
|
|
||||||
|
# Fix ownership and permissions
|
||||||
|
sudo chown root:root /usr/bin/netbird
|
||||||
|
sudo chmod +x /usr/bin/netbird
|
||||||
|
|
||||||
|
# Fix SELinux context (RHEL/Fedora)
|
||||||
|
sudo restorecon -v /usr/bin/netbird
|
||||||
|
|
||||||
|
# Restart service
|
||||||
|
sudo systemctl restart netbird
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Update Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current version
|
||||||
|
netbird version
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
sudo systemctl status netbird
|
||||||
|
|
||||||
|
# View update logs
|
||||||
|
sudo cat /var/log/netbird-update.log
|
||||||
|
|
||||||
|
# Check timer status (if installed)
|
||||||
|
systemctl status netbird-update.timer
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Update
|
||||||
|
|
||||||
|
If you need to manually trigger an update:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./netbird-install-update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use the official Netbird update method:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://pkgs.netbird.io/install.sh | sudo UPDATE_NETBIRD=true sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timer Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check timer status
|
||||||
|
systemctl status netbird-update.timer
|
||||||
|
|
||||||
|
# View timer schedule
|
||||||
|
systemctl list-timers netbird-update.timer
|
||||||
|
|
||||||
|
# Manually trigger timer
|
||||||
|
sudo systemctl start netbird-update.service
|
||||||
|
|
||||||
|
# Disable timer
|
||||||
|
sudo systemctl disable --now netbird-update.timer
|
||||||
|
|
||||||
|
# Remove timer completely
|
||||||
|
sudo systemctl disable --now netbird-update.timer
|
||||||
|
sudo rm /etc/systemd/system/netbird-update.service
|
||||||
|
sudo rm /etc/systemd/system/netbird-update.timer
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why Binary Install?
|
||||||
|
|
||||||
|
The script converts package manager installations to binary installs because:
|
||||||
|
|
||||||
|
1. **Better Control**: Direct binary management allows precise version control
|
||||||
|
2. **Simpler Updates**: Binary updates don't require package manager configuration
|
||||||
|
3. **Consistency**: Same installation method across all Linux distributions
|
||||||
|
4. **Official Support**: Binary install is the officially recommended method by Netbird
|
||||||
|
|
||||||
|
## Remote Deployment Details
|
||||||
|
|
||||||
|
When deploying remotely:
|
||||||
|
|
||||||
|
1. Script copies itself to the remote host via `scp`
|
||||||
|
2. Executes remotely with `sudo` via `ssh -t` (terminal allocation for sudo password prompt)
|
||||||
|
3. Passes through additional flags (like `--timer`)
|
||||||
|
4. Cleans up the remote copy after execution
|
||||||
|
|
||||||
|
The remote deployment continues even if the local script is interrupted.
|
||||||
|
|
||||||
|
**Important Requirements**:
|
||||||
|
- **SSH Authentication**: Remote deployment requires SSH key authentication. Password-based SSH authentication is not supported.
|
||||||
|
- **Sudo Access**: The script will prompt for the sudo password on each remote host. For fully automated deployments, configure passwordless sudo on the remote hosts (e.g., add a sudoers rule like `username ALL=(ALL) NOPASSWD: /bin/bash`).
|
||||||
|
|
||||||
|
### SSH Timeout and Error Handling
|
||||||
|
|
||||||
|
The script includes a 30-second timeout for SSH connections to prevent hanging on unreachable hosts. If a host is unreachable or the connection times out, the script will:
|
||||||
|
|
||||||
|
- Mark the host as failed in the deployment summary
|
||||||
|
- Continue to the next host in the list
|
||||||
|
- Report the failure at the end
|
||||||
|
|
||||||
|
### Deployment Summary
|
||||||
|
|
||||||
|
After multi-host deployment, the script provides a detailed summary showing:
|
||||||
|
|
||||||
|
- **Total successful and failed deployments**
|
||||||
|
- **List of successful hosts** with the action performed:
|
||||||
|
- `fresh install` - Netbird was not installed and has been installed
|
||||||
|
- `pkg replacement` - Netbird was installed via package manager and converted to binary install
|
||||||
|
- `updated` - Netbird was updated to a newer version
|
||||||
|
- `up to date` - Netbird was already at the latest version
|
||||||
|
- **List of failed hosts** that could not be reached or had errors
|
||||||
|
|
||||||
|
Example output:
|
||||||
|
|
||||||
|
```
|
||||||
|
╔═══════════════════════════════════════════════════════════════╗
|
||||||
|
║ ✓ Deployment Summary
|
||||||
|
╠═══════════════════════════════════════════════════════════════╣
|
||||||
|
║ ✓ Successful: 3
|
||||||
|
║ ✗ Failed: 1
|
||||||
|
╚═══════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
Successful Hosts:
|
||||||
|
✓ host-01.example.com (updated)
|
||||||
|
✓ host-02.example.com (fresh install)
|
||||||
|
✓ host-03.example.com (up to date)
|
||||||
|
|
||||||
|
Failed Hosts:
|
||||||
|
✗ host-04.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exit Codes
|
||||||
|
|
||||||
|
- `0`: Success
|
||||||
|
- `1`: Error (file not found, SSH failure, etc.)
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
### Tested Package Managers
|
||||||
|
|
||||||
|
- apt (Debian/Ubuntu)
|
||||||
|
- yum (RHEL/CentOS 7)
|
||||||
|
- dnf (Fedora/RHEL 8+/CentOS 8+)
|
||||||
|
- zypper (openSUSE)
|
||||||
|
- rpm-ostree (Fedora Silverblue)
|
||||||
|
|
||||||
|
### SELinux Support
|
||||||
|
|
||||||
|
Automatically handles SELinux contexts on systems with SELinux enabled (RHEL, Fedora, CentOS). The `restorecon` command is safely ignored on systems without SELinux.
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- Script requires root/sudo access
|
||||||
|
- Downloads official Netbird installer from `https://pkgs.netbird.io/install.sh`
|
||||||
|
- All operations are logged to `/var/log/netbird-update.log`
|
||||||
|
- No credentials are stored or transmitted
|
||||||
|
- Temporary files are cleaned up automatically
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- Linux only (no macOS or Windows support)
|
||||||
|
- Requires SSH key authentication for remote deployment (password authentication is not supported)
|
||||||
|
- Background updates cannot be cancelled once started
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This script is provided as-is for managing Netbird installations. Netbird itself is subject to its own license terms.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please ensure:
|
||||||
|
- Script syntax is valid (`bash -n script.sh`)
|
||||||
|
- Changes are tested on multiple Linux distributions
|
||||||
|
- SELinux compatibility is maintained
|
||||||
|
- No artifacts are left behind after execution
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For Netbird-specific issues, refer to the [official Netbird documentation](https://docs.netbird.io).
|
||||||
|
|
||||||
|
For script-specific issues, check the troubleshooting section or review the logs at `/var/log/netbird-update.log`.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Example hosts file for netbird-install-update.sh
|
||||||
|
# Format: hostname [sudo_password]
|
||||||
|
# One host per line, comments start with #
|
||||||
|
# Host-specific passwords override --password flag
|
||||||
|
|
||||||
|
# Production servers (with host-specific sudo passwords)
|
||||||
|
prod-web-01.jeremy.skynet MySudoPassword123
|
||||||
|
prod-web-02.jeremy.skynet MySudoPassword123
|
||||||
|
prod-db-01.jeremy.skynet MySudoPassword123
|
||||||
|
|
||||||
|
# Development servers (will use --password flag or prompt interactively)
|
||||||
|
dev-app-01.jeremy.skynet
|
||||||
|
dev-app-02.jeremy.skynet
|
||||||
|
|
||||||
|
# You can also use IP addresses
|
||||||
|
# 192.168.1.100
|
||||||
|
# 10.0.0.50 MyPassword
|
||||||
+434
@@ -0,0 +1,434 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Color codes for output formatting
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
DIM='\033[2m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Icons
|
||||||
|
ICON_SUCCESS="✓"
|
||||||
|
ICON_ERROR="✗"
|
||||||
|
ICON_INFO="ℹ"
|
||||||
|
ICON_WARNING="⚠"
|
||||||
|
ICON_ARROW="→"
|
||||||
|
ICON_DOWNLOAD="⬇"
|
||||||
|
ICON_UPLOAD="⬆"
|
||||||
|
ICON_INSTALL="📦"
|
||||||
|
ICON_UPDATE="🔄"
|
||||||
|
ICON_DEPLOY="🚀"
|
||||||
|
ICON_TIMER="⏰"
|
||||||
|
ICON_CHECK="🔍"
|
||||||
|
ICON_CONFIG="⚙"
|
||||||
|
ICON_NETWORK="🌐"
|
||||||
|
ICON_VERSION="📋"
|
||||||
|
ICON_LOG="📝"
|
||||||
|
ICON_HOST="🖥"
|
||||||
|
|
||||||
|
SSH_HOST=""
|
||||||
|
HOSTS_FILE=""
|
||||||
|
INSTALL_TIMER=false
|
||||||
|
TIMER_TIME="daily"
|
||||||
|
DEFAULT_PASSWORD=""
|
||||||
|
REMOTE_ARGS=()
|
||||||
|
SSH_TIMEOUT=30
|
||||||
|
|
||||||
|
# Arrays to track deployment results
|
||||||
|
declare -a SUCCESS_HOSTS=()
|
||||||
|
declare -a FAILED_HOSTS=()
|
||||||
|
declare -a HOST_ACTIONS=()
|
||||||
|
|
||||||
|
# Helper functions for formatted output
|
||||||
|
print_header() {
|
||||||
|
echo -e "\n${BLUE}${BOLD}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BLUE}${BOLD}║ $1${NC}"
|
||||||
|
echo -e "${BLUE}${BOLD}╚═══════════════════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_info() {
|
||||||
|
echo -e " ${BLUE}${ICON_INFO}${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_success() {
|
||||||
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e " ${RED}${ICON_ERROR}${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_status() {
|
||||||
|
echo -e " ${CYAN}${ICON_ARROW}${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_step() {
|
||||||
|
echo -e " ${DIM}•${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--ssh)
|
||||||
|
SSH_HOST="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--hosts-file|--file)
|
||||||
|
HOSTS_FILE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--timer)
|
||||||
|
INSTALL_TIMER=true
|
||||||
|
REMOTE_ARGS+=("--timer")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--time)
|
||||||
|
TIMER_TIME="$2"
|
||||||
|
REMOTE_ARGS+=("--time" "$2")
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--password|-p)
|
||||||
|
DEFAULT_PASSWORD="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
deploy_to_host() {
|
||||||
|
local host="$1"
|
||||||
|
local sudo_pass="${2:-}"
|
||||||
|
echo -e "${CYAN}${BOLD}┌─────────────────────────────────────────────────────────────┐${NC}"
|
||||||
|
echo -e "${CYAN}${BOLD}│${NC} ${ICON_DEPLOY} ${YELLOW}${host}${NC}"
|
||||||
|
echo -e "${CYAN}${BOLD}└─────────────────────────────────────────────────────────────┘${NC}"
|
||||||
|
|
||||||
|
REMOTE_SCRIPT="/tmp/.netbird-install-update-$$"
|
||||||
|
REMOTE_ACTION_FILE="/tmp/.netbird-action-$$"
|
||||||
|
LOCAL_ACTION_FILE="/tmp/.netbird-deploy-action-$$"
|
||||||
|
|
||||||
|
print_step "Copying script..."
|
||||||
|
if ! scp -o ConnectTimeout=$SSH_TIMEOUT -o BatchMode=yes "$0" "$host:$REMOTE_SCRIPT" 2>&1; then
|
||||||
|
print_error "Failed to copy script to $host (timeout or connection error)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_step "Executing script..."
|
||||||
|
# Build SSH command based on whether we have a password
|
||||||
|
if [ -n "$sudo_pass" ]; then
|
||||||
|
# Write password to remote temp file using printf to handle special characters
|
||||||
|
# Use base64 to safely transfer the password
|
||||||
|
local encoded_pass=$(echo -n "$sudo_pass" | base64)
|
||||||
|
if ! ssh -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no "$host" "echo '$encoded_pass' | base64 -d > /tmp/.netbird-pass-$$ && chmod 600 /tmp/.netbird-pass-$$" 2>&1; then
|
||||||
|
print_error "Failed to setup password file on $host"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute script with sudo, reading password from file
|
||||||
|
if ! ssh -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no "$host" "sudo -S bash $REMOTE_SCRIPT ${REMOTE_ARGS[*]} < /tmp/.netbird-pass-$$" 2>&1; then
|
||||||
|
print_error "Failed to execute script on $host"
|
||||||
|
ssh -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no "$host" "rm -f $REMOTE_SCRIPT $REMOTE_ACTION_FILE /tmp/.netbird-pass-$$" 2>/dev/null || true
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up password file
|
||||||
|
ssh -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no "$host" "rm -f /tmp/.netbird-pass-$$" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
# Interactive sudo with terminal
|
||||||
|
if ! ssh -o ConnectTimeout=$SSH_TIMEOUT -o BatchMode=yes -t "$host" "sudo bash $REMOTE_SCRIPT ${REMOTE_ARGS[*]}" 2>&1; then
|
||||||
|
print_error "Failed to execute script on $host"
|
||||||
|
ssh -o ConnectTimeout=$SSH_TIMEOUT -o BatchMode=yes "$host" "rm -f $REMOTE_SCRIPT $REMOTE_ACTION_FILE" 2>/dev/null || true
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read the action from the remote action file and write to local action file
|
||||||
|
if action_output=$(ssh -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no "$host" "cat $REMOTE_ACTION_FILE 2>/dev/null" < /dev/null 2>&1); then
|
||||||
|
echo "$action_output" > "$LOCAL_ACTION_FILE"
|
||||||
|
else
|
||||||
|
echo "unknown" > "$LOCAL_ACTION_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up remote files
|
||||||
|
ssh -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no "$host" "rm -f $REMOTE_SCRIPT $REMOTE_ACTION_FILE" < /dev/null 2>/dev/null || true
|
||||||
|
print_success "Completed: $host"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -n "$HOSTS_FILE" ]; then
|
||||||
|
if [ ! -f "$HOSTS_FILE" ]; then
|
||||||
|
print_error "Hosts file not found: $HOSTS_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_header "${ICON_NETWORK} Multi-Host Deployment"
|
||||||
|
print_info "Reading hosts from: ${YELLOW}$HOSTS_FILE${NC}"
|
||||||
|
print_info "SSH timeout: ${YELLOW}${SSH_TIMEOUT}s${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
SUCCESS_COUNT=0
|
||||||
|
FAIL_COUNT=0
|
||||||
|
ACTION_FILE="/tmp/.netbird-deploy-action-$$"
|
||||||
|
|
||||||
|
# Use file descriptor 3 to read hosts file (prevents SSH from consuming stdin)
|
||||||
|
exec 3< "$HOSTS_FILE"
|
||||||
|
while IFS= read -r line <&3 || [ -n "$line" ]; do
|
||||||
|
# Skip empty lines and comments
|
||||||
|
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
||||||
|
# Trim whitespace
|
||||||
|
line=$(echo "$line" | xargs)
|
||||||
|
|
||||||
|
# Parse hostname and optional password
|
||||||
|
host=$(echo "$line" | awk '{print $1}')
|
||||||
|
sudo_pass=$(echo "$line" | awk '{print $2}')
|
||||||
|
|
||||||
|
# Use default password if no host-specific password is provided
|
||||||
|
if [ -z "$sudo_pass" ] && [ -n "$DEFAULT_PASSWORD" ]; then
|
||||||
|
sudo_pass="$DEFAULT_PASSWORD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run deployment (output streams to terminal)
|
||||||
|
if deploy_to_host "$host" "$sudo_pass"; then
|
||||||
|
# Read the action from the temp file
|
||||||
|
action="unknown"
|
||||||
|
if [ -f "$ACTION_FILE" ]; then
|
||||||
|
action=$(cat "$ACTION_FILE")
|
||||||
|
rm -f "$ACTION_FILE"
|
||||||
|
fi
|
||||||
|
SUCCESS_HOSTS+=("$host")
|
||||||
|
HOST_ACTIONS+=("$action")
|
||||||
|
((SUCCESS_COUNT++)) || true
|
||||||
|
else
|
||||||
|
FAILED_HOSTS+=("$host")
|
||||||
|
((FAIL_COUNT++)) || true
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
exec 3<&-
|
||||||
|
|
||||||
|
# Print detailed summary
|
||||||
|
echo -e "\n${GREEN}${BOLD}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${GREEN}${BOLD}║${NC} ${ICON_SUCCESS} ${GREEN}${BOLD}Deployment Summary${NC}"
|
||||||
|
echo -e "${GREEN}${BOLD}╠═══════════════════════════════════════════════════════════════╣${NC}"
|
||||||
|
echo -e "${GREEN}${BOLD}║${NC} ${GREEN}${ICON_SUCCESS}${NC} Successful: ${BOLD}$SUCCESS_COUNT${NC}"
|
||||||
|
echo -e "${GREEN}${BOLD}║${NC} ${RED}${ICON_ERROR}${NC} Failed: ${BOLD}$FAIL_COUNT${NC}"
|
||||||
|
echo -e "${GREEN}${BOLD}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||||
|
|
||||||
|
# Show successful hosts with actions
|
||||||
|
if [ ${#SUCCESS_HOSTS[@]} -gt 0 ]; then
|
||||||
|
echo -e "\n${GREEN}${BOLD}Successful Hosts:${NC}"
|
||||||
|
for i in "${!SUCCESS_HOSTS[@]}"; do
|
||||||
|
host="${SUCCESS_HOSTS[$i]}"
|
||||||
|
action="${HOST_ACTIONS[$i]}"
|
||||||
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} ${YELLOW}$host${NC} ${DIM}($action)${NC}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show failed hosts
|
||||||
|
if [ ${#FAILED_HOSTS[@]} -gt 0 ]; then
|
||||||
|
echo -e "\n${RED}${BOLD}Failed Hosts:${NC}"
|
||||||
|
for host in "${FAILED_HOSTS[@]}"; do
|
||||||
|
echo -e " ${RED}${ICON_ERROR}${NC} ${YELLOW}$host${NC}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SSH_HOST" ]; then
|
||||||
|
print_header "${ICON_DEPLOY} Single Host Deployment"
|
||||||
|
ACTION_FILE="/tmp/.netbird-deploy-action-$$"
|
||||||
|
if deploy_to_host "$SSH_HOST" "$DEFAULT_PASSWORD"; then
|
||||||
|
# Read and display the action
|
||||||
|
if [ -f "$ACTION_FILE" ]; then
|
||||||
|
action=$(cat "$ACTION_FILE")
|
||||||
|
rm -f "$ACTION_FILE"
|
||||||
|
print_info "Action performed: ${YELLOW}$action${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
print_warning "Elevating to root..."
|
||||||
|
exec sudo "$0" "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORK_DIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||||
|
|
||||||
|
detect_install() {
|
||||||
|
if ! command -v netbird &>/dev/null; then
|
||||||
|
echo "none"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /etc/netbird/install.conf ]; then
|
||||||
|
local pm
|
||||||
|
pm=$(grep -oP 'package_manager=\K.*' /etc/netbird/install.conf 2>/dev/null || true)
|
||||||
|
if [ "$pm" = "bin" ]; then
|
||||||
|
echo "bin"
|
||||||
|
return
|
||||||
|
elif [ -n "$pm" ]; then
|
||||||
|
echo "pkg:$pm"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if dpkg -s netbird &>/dev/null; then
|
||||||
|
echo "pkg:apt"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if rpm -q netbird &>/dev/null; then
|
||||||
|
if command -v dnf &>/dev/null; then
|
||||||
|
echo "pkg:dnf"
|
||||||
|
else
|
||||||
|
echo "pkg:yum"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_timer() {
|
||||||
|
print_header "${ICON_TIMER} Installing Auto-Update Timer"
|
||||||
|
|
||||||
|
if systemctl is-active --quiet netbird-update.timer; then
|
||||||
|
print_warning "Updating existing timer..."
|
||||||
|
systemctl stop netbird-update.timer
|
||||||
|
systemctl disable netbird-update.timer
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/netbird-update.service <<'UNIT'
|
||||||
|
[Unit]
|
||||||
|
Description=Netbird Auto-Update
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/bin/bash -c 'curl -fsSL https://pkgs.netbird.io/install.sh | UPDATE_NETBIRD=true sh && chown root:root /usr/bin/netbird 2>/dev/null || true && chmod +x /usr/bin/netbird 2>/dev/null || true && restorecon -v /usr/bin/netbird 2>/dev/null || true && systemctl restart netbird 2>/dev/null || true'
|
||||||
|
StandardOutput=append:/var/log/netbird-update.log
|
||||||
|
StandardError=append:/var/log/netbird-update.log
|
||||||
|
UNIT
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/netbird-update.timer <<UNIT
|
||||||
|
[Unit]
|
||||||
|
Description=Run Netbird update daily
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=$TIMER_TIME
|
||||||
|
Persistent=true
|
||||||
|
RandomizedDelaySec=600
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
UNIT
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now netbird-update.timer
|
||||||
|
|
||||||
|
print_success "Timer installed successfully"
|
||||||
|
print_info "Schedule: ${YELLOW}$TIMER_TIME${NC} (with random 0-10 minute delay)"
|
||||||
|
print_info "Logs: ${YELLOW}/var/log/netbird-update.log${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_header "${ICON_INSTALL} NetBird Install/Update"
|
||||||
|
|
||||||
|
print_status "${ICON_DOWNLOAD} Downloading Netbird install script..."
|
||||||
|
curl -fsSL -o "$WORK_DIR/install.sh" https://pkgs.netbird.io/install.sh
|
||||||
|
chmod +x "$WORK_DIR/install.sh"
|
||||||
|
print_success "Download complete"
|
||||||
|
|
||||||
|
print_status "${ICON_CHECK} Detecting installation state..."
|
||||||
|
state=$(detect_install)
|
||||||
|
print_info "Detected: ${YELLOW}$state${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
case "$state" in
|
||||||
|
none)
|
||||||
|
print_header "${ICON_INSTALL} Fresh Installation"
|
||||||
|
print_info "Netbird not found. Installing..."
|
||||||
|
USE_BIN_INSTALL=true SKIP_UI_APP=true "$WORK_DIR/install.sh"
|
||||||
|
chown root:root /usr/bin/netbird 2>/dev/null || true
|
||||||
|
restorecon -v /usr/bin/netbird 2>/dev/null || true
|
||||||
|
systemctl restart netbird 2>/dev/null || true
|
||||||
|
print_success "Netbird installed successfully"
|
||||||
|
echo "fresh install" > /tmp/.netbird-action-$$
|
||||||
|
;;
|
||||||
|
pkg:*)
|
||||||
|
print_header "${ICON_UPDATE} Package Manager Replacement"
|
||||||
|
pm="${state#pkg:}"
|
||||||
|
print_info "Netbird installed via ${YELLOW}$pm${NC}"
|
||||||
|
print_info "Replacing with binary install..."
|
||||||
|
cat > /tmp/.netbird_replace.sh <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
sleep 3
|
||||||
|
systemctl stop netbird 2>/dev/null || true
|
||||||
|
case "$1" in
|
||||||
|
apt) apt-get remove -y netbird netbird-ui 2>/dev/null || true ;;
|
||||||
|
yum) yum remove -y netbird netbird-ui 2>/dev/null || true ;;
|
||||||
|
dnf) dnf remove -y netbird netbird-ui 2>/dev/null || true ;;
|
||||||
|
zypper) zypper remove -y netbird netbird-ui 2>/dev/null || true ;;
|
||||||
|
rpm-ostree) rpm-ostree uninstall -y netbird netbird-ui 2>/dev/null || true ;;
|
||||||
|
esac
|
||||||
|
USE_BIN_INSTALL=true SKIP_UI_APP=true bash /tmp/.netbird_install.sh
|
||||||
|
chown root:root /usr/bin/netbird 2>/dev/null || true
|
||||||
|
chmod +x /usr/bin/netbird 2>/dev/null || true
|
||||||
|
restorecon -v /usr/bin/netbird 2>/dev/null || true
|
||||||
|
systemctl restart netbird 2>/dev/null || true
|
||||||
|
rm -f /tmp/.netbird_replace.sh /tmp/.netbird_install.sh
|
||||||
|
EOF
|
||||||
|
chmod +x /tmp/.netbird_replace.sh
|
||||||
|
cp "$WORK_DIR/install.sh" /tmp/.netbird_install.sh
|
||||||
|
setsid bash /tmp/.netbird_replace.sh "$pm" </dev/null >/var/log/netbird-update.log 2>&1 &
|
||||||
|
print_warning "Replacement scheduled in background"
|
||||||
|
print_info "Connection may drop momentarily"
|
||||||
|
print_info "Check ${YELLOW}/var/log/netbird-update.log${NC} for progress"
|
||||||
|
echo "pkg replacement" > /tmp/.netbird-action-$$
|
||||||
|
;;
|
||||||
|
bin)
|
||||||
|
print_header "${ICON_VERSION} Binary Update Check"
|
||||||
|
if [ ! -f /etc/netbird/install.conf ]; then
|
||||||
|
mkdir -p /etc/netbird
|
||||||
|
echo "package_manager=bin" > /etc/netbird/install.conf
|
||||||
|
fi
|
||||||
|
current=$(netbird version 2>/dev/null || echo "unknown")
|
||||||
|
latest=$(curl -fsSL https://pkgs.netbird.io/releases/latest 2>/dev/null | grep -oP '"tag_name":\s*"v?\K[^"]+' || echo "unknown")
|
||||||
|
|
||||||
|
print_info "Current version: ${YELLOW}$current${NC}"
|
||||||
|
print_info "Latest version: ${YELLOW}$latest${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$current" = "$latest" ] && [ "$current" != "unknown" ]; then
|
||||||
|
print_success "Netbird is up to date"
|
||||||
|
echo "up to date" > /tmp/.netbird-action-$$
|
||||||
|
else
|
||||||
|
print_info "Updating Netbird: ${YELLOW}$current${NC} → ${GREEN}$latest${NC}"
|
||||||
|
cp "$WORK_DIR/install.sh" /tmp/.netbird_update.sh
|
||||||
|
setsid bash -c 'sleep 3 && bash /tmp/.netbird_update.sh --update && chown root:root /usr/bin/netbird 2>/dev/null || true && chmod +x /usr/bin/netbird 2>/dev/null || true && restorecon -v /usr/bin/netbird 2>/dev/null || true && systemctl restart netbird 2>/dev/null || true && rm -f /tmp/.netbird_update.sh' \
|
||||||
|
</dev/null >/var/log/netbird-update.log 2>&1 &
|
||||||
|
print_warning "Update scheduled in background"
|
||||||
|
print_info "Connection may drop momentarily"
|
||||||
|
print_info "Check ${YELLOW}/var/log/netbird-update.log${NC} for progress"
|
||||||
|
echo "updated" > /tmp/.netbird-action-$$
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if $INSTALL_TIMER; then
|
||||||
|
install_timer
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Test SSH remote execution
|
||||||
|
echo "=== Testing SSH remote execution ==="
|
||||||
|
echo ""
|
||||||
|
echo "Usage examples:"
|
||||||
|
echo " ./netbird-install-update.sh # Run locally"
|
||||||
|
echo " ./netbird-install-update.sh --timer # Run locally with auto-update timer"
|
||||||
|
echo " ./netbird-install-update.sh --ssh user@host # Deploy to remote host"
|
||||||
|
echo " ./netbird-install-update.sh --ssh user@host --timer # Deploy to remote host with timer"
|
||||||
|
echo ""
|
||||||
|
echo "The -ssh flag will:"
|
||||||
|
echo "1. Copy this script to the remote host via scp"
|
||||||
|
echo "2. Execute it remotely with sudo"
|
||||||
|
echo "3. Pass through any other flags (like --timer)"
|
||||||
|
echo "4. Clean up the remote copy after execution"
|
||||||
|
echo ""
|
||||||
|
echo "Script is ready for testing!"
|
||||||
Reference in New Issue
Block a user