Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions cmd/proxsave/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,6 @@ func runConfigWizardCLI(ctx context.Context, reader *bufio.Reader, configPath, t
return false, false, wrapInstallError(err)
}

// Ensure BASE_DIR is explicitly present in the generated env file so that
// subsequent runs and encryption setup use the same root directory.
template = setEnvValue(template, "BASE_DIR", baseDir)

logging.DebugStepBootstrap(bootstrap, "install config wizard (cli)", "writing configuration")
if err := writeConfigFile(configPath, tmpConfigPath, template); err != nil {
return false, false, err
Expand Down
19 changes: 18 additions & 1 deletion cmd/proxsave/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,7 @@
}
fmt.Printf("\r Remaining: %ds ", int(remaining.Seconds()))

select {

Check failure on line 1572 in cmd/proxsave/main.go

View workflow job for this annotation

GitHub Actions / security

should use a simple channel send/receive instead of select with a single case (S1000)

Check failure on line 1572 in cmd/proxsave/main.go

View workflow job for this annotation

GitHub Actions / security

should use a simple channel send/receive instead of select with a single case (S1000)
case <-ticker.C:
continue
}
Expand All @@ -1581,14 +1581,31 @@
func printFinalSummary(finalExitCode int) {
fmt.Println()

// Print a flat list of all WARNING/ERROR/CRITICAL log entries that occurred during the run.
// This makes it easy to spot the root cause(s) behind a WARNING/ERROR exit status without
// scrolling through the full log.
logger := logging.GetDefaultLogger()
if logger != nil {
issues := logger.IssueLines()
if len(issues) > 0 {
fmt.Println("===========================================")
fmt.Printf("WARNINGS/ERRORS DURING RUN (warnings=%d errors=%d)\n", logger.WarningCount(), logger.ErrorCount())
fmt.Println()
for _, line := range issues {
fmt.Println(line)
}
fmt.Println("===========================================")
fmt.Println()
}
}

summarySig := buildSignature()
if summarySig == "" {
summarySig = "unknown"
}

colorReset := "\033[0m"
color := ""
logger := logging.GetDefaultLogger()
hasWarnings := logger != nil && logger.HasWarnings()

switch {
Expand Down
7 changes: 7 additions & 0 deletions docs/BACKUP_ENV_MAPPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ WEBHOOK_TIMEOUT = SAME
## Go-only variables (new)

SYSTEM_ROOT_PREFIX = NEW (Go-only) → Override system root for collection (testing/chroot). Empty or "/" uses the real root.
BACKUP_PBS_S3_ENDPOINTS = NEW (Go-only) → Collect `s3.cfg` and S3 endpoint snapshots (PBS).
BACKUP_PBS_NODE_CONFIG = NEW (Go-only) → Collect `node.cfg` and node snapshots (PBS).
BACKUP_PBS_ACME_ACCOUNTS = NEW (Go-only) → Collect `acme/accounts.cfg` and ACME account snapshots (PBS).
BACKUP_PBS_ACME_PLUGINS = NEW (Go-only) → Collect `acme/plugins.cfg` and ACME plugin snapshots (PBS).
BACKUP_PBS_METRIC_SERVERS = NEW (Go-only) → Collect `metricserver.cfg` (PBS).
BACKUP_PBS_TRAFFIC_CONTROL = NEW (Go-only) → Collect `traffic-control.cfg` and traffic-control snapshots (PBS).
BACKUP_PBS_NETWORK_CONFIG = NEW (Go-only) → Collect `network.cfg` and network snapshots (PBS), independent from BACKUP_NETWORK_CONFIGS (system).

## Renamed variables / Supported aliases in Go

Expand Down
10 changes: 7 additions & 3 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,9 @@ MIN_DISK_SPACE_CLOUD_GB=1 # Cloud storage (not enforced for remote)
## Storage Paths

```bash
# Base directory for all operations
BASE_DIR=/opt/proxsave
# Base directory for all operations (auto-detected at runtime)
# BASE_DIR is derived from the executable/config location, so it is usually not
# written in backup.env.

# Lock file directory
LOCK_PATH=${BASE_DIR}/lock
Expand Down Expand Up @@ -787,7 +788,10 @@ EMAIL_FROM=no-reply@proxmox.tis24.it
- Allowed values for `EMAIL_DELIVERY_METHOD` are: `relay`, `sendmail`, `pmf` (invalid values will skip Email with a warning).
- `EMAIL_FALLBACK_SENDMAIL` is a historical name (kept for compatibility). When `EMAIL_DELIVERY_METHOD=relay`, it enables fallback to **pmf** (it will not fall back to `/usr/sbin/sendmail`).
- `relay` requires a real mailbox recipient and blocks `root@…` recipients; set `EMAIL_RECIPIENT` to a non-root mailbox if needed.
- `sendmail` requires a recipient and uses `/usr/sbin/sendmail`; ProxSave can auto-detect `root@pam` email from Proxmox if `EMAIL_RECIPIENT` is empty.
- If `EMAIL_RECIPIENT` is empty, ProxSave auto-detects the recipient from the `root@pam` user:
- **PVE**: Proxmox API via `pvesh get /access/users/root@pam` → fallback to `pveum user list` → fallback to `/etc/pve/user.cfg`
- **PBS**: `proxmox-backup-manager user list` → fallback to `/etc/proxmox-backup/user.cfg`
- `sendmail` requires a recipient and uses `/usr/sbin/sendmail` (auto-detect applies if `EMAIL_RECIPIENT` is empty, as described above).
- With `pmf`, final delivery recipients are determined by Proxmox Notifications targets/matchers. `EMAIL_RECIPIENT` is only used for the `To:` header and may be empty.

### Gotify
Expand Down
25 changes: 25 additions & 0 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,17 +534,42 @@ If Email is enabled but you don't see it being dispatched, ensure `EMAIL_DELIVER
- Ensure the recipient is configured:
- Set `EMAIL_RECIPIENT=...`, or
- Leave it empty and set an email for `root@pam` inside Proxmox (auto-detect).
- Recipient auto-detection details (when `EMAIL_RECIPIENT` is empty):
- **PVE**: `pvesh get /access/users/root@pam` → fallback to `pveum user list` → fallback to `/etc/pve/user.cfg`
- **PBS**: `proxmox-backup-manager user list` → fallback to `/etc/proxmox-backup/user.cfg`
- Relay blocks `root@…` recipients; use a real non-root mailbox for `EMAIL_RECIPIENT`.
- If `EMAIL_FALLBACK_SENDMAIL=true`, ProxSave will fall back to `EMAIL_DELIVERY_METHOD=pmf` when the relay fails.
- Check the proxsave logs for `email-relay` warnings/errors.

Quick checks for auto-detect:

```bash
# Run only the relevant block for your platform (PVE vs PBS).

# PVE (preferred: API via pvesh)
pvesh get /access/users/root@pam --output-format json

# PVE (fallback: legacy CLI)
pveum user list --output-format json

# PVE (last resort: config file)
grep -n '^user:root@pam:' /etc/pve/user.cfg

# PBS (CLI)
proxmox-backup-manager user list --output-format json

# PBS (config file)
grep -n '^user:root@pam:' /etc/proxmox-backup/user.cfg
```

##### If `EMAIL_DELIVERY_METHOD=sendmail`

This mode uses `/usr/sbin/sendmail`, so your node must have a working local MTA (e.g. postfix).

- Ensure a recipient is available:
- Set `EMAIL_RECIPIENT=...`, or
- Leave it empty and set an email for `root@pam` inside Proxmox (auto-detect).
- If auto-detection fails, run the quick checks above and review proxsave debug logs (they include diagnostic output from failed Proxmox CLI/API calls).
- Verify `sendmail` exists:
```bash
test -x /usr/sbin/sendmail && echo "sendmail OK" || echo "sendmail not found"
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/tis24dev/proxsave

go 1.25

toolchain go1.25.6
toolchain go1.25.7

require (
filippo.io/age v1.3.1
Expand Down
52 changes: 34 additions & 18 deletions internal/backup/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,21 @@ type CollectorConfig struct {
CephConfigPath string

// PBS-specific collection options
BackupDatastoreConfigs bool
BackupUserConfigs bool
BackupRemoteConfigs bool
BackupSyncJobs bool
BackupVerificationJobs bool
BackupTapeConfigs bool
BackupPruneSchedules bool
BackupPxarFiles bool
BackupDatastoreConfigs bool
BackupPBSS3Endpoints bool
BackupPBSNodeConfig bool
BackupPBSAcmeAccounts bool
BackupPBSAcmePlugins bool
BackupPBSMetricServers bool
BackupPBSTrafficControl bool
BackupUserConfigs bool
BackupRemoteConfigs bool
BackupSyncJobs bool
BackupVerificationJobs bool
BackupTapeConfigs bool
BackupPBSNetworkConfig bool
BackupPruneSchedules bool
BackupPxarFiles bool

// System collection options
BackupNetworkConfigs bool
Expand Down Expand Up @@ -242,9 +249,11 @@ func (c *CollectorConfig) Validate() error {
c.BackupPVEFirewall || c.BackupVZDumpConfig || c.BackupPVEACL ||
c.BackupPVEJobs || c.BackupPVESchedules || c.BackupPVEReplication ||
c.BackupPVEBackupFiles || c.BackupCephConfig ||
c.BackupDatastoreConfigs || c.BackupUserConfigs || c.BackupRemoteConfigs ||
c.BackupDatastoreConfigs || c.BackupPBSS3Endpoints || c.BackupPBSNodeConfig ||
c.BackupPBSAcmeAccounts || c.BackupPBSAcmePlugins || c.BackupPBSMetricServers ||
c.BackupPBSTrafficControl || c.BackupUserConfigs || c.BackupRemoteConfigs ||
c.BackupSyncJobs || c.BackupVerificationJobs || c.BackupTapeConfigs ||
c.BackupPruneSchedules || c.BackupPxarFiles ||
c.BackupPBSNetworkConfig || c.BackupPruneSchedules || c.BackupPxarFiles ||
c.BackupNetworkConfigs || c.BackupAptSources || c.BackupCronJobs ||
c.BackupSystemdServices || c.BackupSSLCerts || c.BackupSysctlConfig ||
c.BackupKernelModules || c.BackupFirewallRules ||
Expand Down Expand Up @@ -322,14 +331,21 @@ func GetDefaultCollectorConfig() *CollectorConfig {
CephConfigPath: "/etc/ceph",

// PBS-specific (all enabled by default)
BackupDatastoreConfigs: true,
BackupUserConfigs: true,
BackupRemoteConfigs: true,
BackupSyncJobs: true,
BackupVerificationJobs: true,
BackupTapeConfigs: true,
BackupPruneSchedules: true,
BackupPxarFiles: true,
BackupDatastoreConfigs: true,
BackupPBSS3Endpoints: true,
BackupPBSNodeConfig: true,
BackupPBSAcmeAccounts: true,
BackupPBSAcmePlugins: true,
BackupPBSMetricServers: true,
BackupPBSTrafficControl: true,
BackupUserConfigs: true,
BackupRemoteConfigs: true,
BackupSyncJobs: true,
BackupVerificationJobs: true,
BackupTapeConfigs: true,
BackupPBSNetworkConfig: true,
BackupPruneSchedules: true,
BackupPxarFiles: true,

// System collection (all enabled by default)
BackupNetworkConfigs: true,
Expand Down
Loading
Loading