or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

archives.mdindex.mdmaintenance.mdmount.mdrepository.mdutilities.md

maintenance.mddocs/

0

# Pruning and Maintenance

1

2

Archive pruning, repository maintenance, and cleanup operations for managing backup retention policies and optimizing repository storage in BorgBackup.

3

4

```python

5

import subprocess

6

```

7

8

## Capabilities

9

10

### Archive Pruning

11

12

Automatically remove old archives based on retention policies to manage storage space and backup history.

13

14

```python { .api }

15

def prune_archives(repo_path: str, keep_within: str = None, keep_daily: int = None,

16

keep_weekly: int = None, keep_monthly: int = None,

17

keep_yearly: int = None, dry_run: bool = False,

18

stats: bool = False, list_archives: bool = False) -> None:

19

"""

20

Prune archives based on retention policy.

21

22

Args:

23

repo_path: Path to repository

24

keep_within: Keep archives within time period (e.g., '1d', '7d', '1m', '1y')

25

keep_daily: Number of daily archives to keep

26

keep_weekly: Number of weekly archives to keep

27

keep_monthly: Number of monthly archives to keep

28

keep_yearly: Number of yearly archives to keep

29

dry_run: Show what would be pruned without pruning

30

stats: Show pruning statistics

31

list_archives: List archives that would be kept/pruned

32

"""

33

cmd = ['borg', 'prune']

34

if keep_within:

35

cmd.extend(['--keep-within', keep_within])

36

if keep_daily:

37

cmd.extend(['--keep-daily', str(keep_daily)])

38

if keep_weekly:

39

cmd.extend(['--keep-weekly', str(keep_weekly)])

40

if keep_monthly:

41

cmd.extend(['--keep-monthly', str(keep_monthly)])

42

if keep_yearly:

43

cmd.extend(['--keep-yearly', str(keep_yearly)])

44

if dry_run:

45

cmd.append('--dry-run')

46

if stats:

47

cmd.append('--stats')

48

if list_archives:

49

cmd.append('--list')

50

51

cmd.append(repo_path)

52

subprocess.run(cmd, check=True)

53

```

54

55

Usage example:

56

```python

57

import subprocess

58

59

# Prune with common retention policy

60

subprocess.run([

61

'borg', 'prune', '--stats',

62

'--keep-daily=7', # Keep 7 daily backups

63

'--keep-weekly=4', # Keep 4 weekly backups

64

'--keep-monthly=6', # Keep 6 monthly backups

65

'--keep-yearly=2', # Keep 2 yearly backups

66

'/backup/repo'

67

], check=True)

68

69

# Prune keeping archives within last 30 days

70

subprocess.run(['borg', 'prune', '--keep-within=30d', '/backup/repo'], check=True)

71

72

# Dry run to see what would be pruned

73

subprocess.run(['borg', 'prune', '--dry-run', '--list', '--keep-daily=7', '/backup/repo'], check=True)

74

```

75

76

### Repository Compaction

77

78

Reclaim space by removing deleted data and optimizing repository storage.

79

80

```python { .api }

81

def compact_repository(repo_path: str, threshold: float = None,

82

dry_run: bool = False, progress: bool = False) -> None:

83

"""

84

Compact repository to reclaim space.

85

86

Args:

87

repo_path: Path to repository

88

threshold: Minimum saved space ratio to trigger compaction (0.0-1.0)

89

dry_run: Show compaction statistics without compacting

90

progress: Show progress during compaction

91

"""

92

cmd = ['borg', 'compact']

93

if threshold:

94

cmd.extend(['--threshold', str(threshold)])

95

if dry_run:

96

cmd.append('--dry-run')

97

if progress:

98

cmd.append('--progress')

99

100

cmd.append(repo_path)

101

subprocess.run(cmd, check=True)

102

```

103

104

Usage example:

105

```python

106

import subprocess

107

108

# Compact repository with progress

109

subprocess.run(['borg', 'compact', '--progress', '/backup/repo'], check=True)

110

111

# Compact only if at least 20% space can be saved

112

subprocess.run(['borg', 'compact', '--threshold=0.2', '/backup/repo'], check=True)

113

114

# Dry run to see potential space savings

115

subprocess.run(['borg', 'compact', '--dry-run', '/backup/repo'], check=True)

116

```

117

118

### Cache Management

119

120

Manage local cache for improved performance, including cache deletion and recreation.

121

122

```python { .api }

123

def delete_cache(repo_path: str, cache_only: bool = False,

124

force: bool = False) -> None:

125

"""

126

Delete repository cache.

127

128

Args:

129

repo_path: Path to repository

130

cache_only: Delete only cache files, not security info

131

force: Force deletion without confirmation

132

"""

133

cmd = ['borg', 'delete']

134

if cache_only:

135

cmd.append('--cache-only')

136

if force:

137

cmd.append('--force')

138

139

cmd.append(repo_path)

140

subprocess.run(cmd, check=True)

141

142

def recreate_cache(repo_path: str, progress: bool = False) -> None:

143

"""

144

Recreate repository cache by reading all archives.

145

146

Args:

147

repo_path: Path to repository

148

progress: Show progress during cache recreation

149

"""

150

# Cache is recreated automatically on next access

151

# Force recreation by listing archives

152

cmd = ['borg', 'list']

153

if progress:

154

cmd.append('--progress')

155

cmd.append(repo_path)

156

subprocess.run(cmd, check=True)

157

```

158

159

Usage example:

160

```python

161

import subprocess

162

163

# Delete cache (will be recreated on next access)

164

subprocess.run(['borg', 'delete', '--cache-only', '/backup/repo'], check=True)

165

166

# Recreate cache by listing archives

167

subprocess.run(['borg', 'list', '/backup/repo'], check=True)

168

```

169

170

### Archive Recreation

171

172

Recreate archives with different settings, such as changing compression or excluding/including different files.

173

174

```python { .api }

175

def recreate_archive(repo_path: str, archive_name: str = None,

176

target_name: str = None, excludes: list = None,

177

compression: str = None, recompress: bool = False,

178

dry_run: bool = False, stats: bool = False) -> None:

179

"""

180

Recreate archive with modified settings.

181

182

Args:

183

repo_path: Path to repository

184

archive_name: Archive to recreate (or pattern)

185

target_name: New archive name

186

excludes: List of exclusion patterns

187

compression: New compression algorithm

188

recompress: Recompress all chunks

189

dry_run: Show what would be recreated

190

stats: Show recreation statistics

191

"""

192

cmd = ['borg', 'recreate']

193

if target_name:

194

cmd.extend(['--target', target_name])

195

if excludes:

196

for exclude in excludes:

197

cmd.extend(['--exclude', exclude])

198

if compression:

199

cmd.extend(['--compression', compression])

200

if recompress:

201

cmd.append('--recompress')

202

if dry_run:

203

cmd.append('--dry-run')

204

if stats:

205

cmd.append('--stats')

206

207

if archive_name:

208

cmd.append(f'{repo_path}::{archive_name}')

209

else:

210

cmd.append(repo_path)

211

212

subprocess.run(cmd, check=True)

213

```

214

215

Usage example:

216

```python

217

import subprocess

218

219

# Recreate archive with better compression

220

subprocess.run([

221

'borg', 'recreate', '--compression=zstd,9', '--recompress',

222

'/backup/repo::old-archive'

223

], check=True)

224

225

# Recreate excluding additional patterns

226

subprocess.run([

227

'borg', 'recreate', '--exclude=*.log', '--exclude=temp/*',

228

'/backup/repo::archive-name'

229

], check=True)

230

231

# Dry run to see what would change

232

subprocess.run([

233

'borg', 'recreate', '--dry-run', '--stats', '--compression=lzma,6',

234

'/backup/repo::test-archive'

235

], check=True)

236

```

237

238

### Repository Upgrading

239

240

Upgrade repository format to newer versions for improved features and performance.

241

242

```python { .api }

243

def upgrade_repository(repo_path: str, dry_run: bool = False,

244

force: bool = False, tam: bool = False) -> None:

245

"""

246

Upgrade repository format.

247

248

Args:

249

repo_path: Path to repository

250

dry_run: Show what would be upgraded

251

force: Force upgrade without confirmation

252

tam: Enable/disable TAM (Tamper Authentication Mode)

253

"""

254

cmd = ['borg', 'upgrade']

255

if dry_run:

256

cmd.append('--dry-run')

257

if force:

258

cmd.append('--force')

259

if tam:

260

cmd.append('--tam')

261

262

cmd.append(repo_path)

263

subprocess.run(cmd, check=True)

264

```

265

266

Usage example:

267

```python

268

import subprocess

269

270

# Upgrade repository (dry run first)

271

subprocess.run(['borg', 'upgrade', '--dry-run', '/backup/repo'], check=True)

272

273

# Perform actual upgrade

274

subprocess.run(['borg', 'upgrade', '/backup/repo'], check=True)

275

```

276

277

### Repository Serving

278

279

Serve repository over SSH for remote access with security restrictions.

280

281

```python { .api }

282

def serve_repository(restrict_to_paths: list = None, restrict_to_repositories: list = None,

283

append_only: bool = False, storage_quota: str = None) -> None:

284

"""

285

Serve repository for remote access (typically called via SSH).

286

287

Args:

288

restrict_to_paths: Restrict access to specific paths

289

restrict_to_repositories: Restrict access to specific repositories

290

append_only: Allow only append operations

291

storage_quota: Set storage quota limit

292

"""

293

cmd = ['borg', 'serve']

294

if restrict_to_paths:

295

cmd.extend(['--restrict-to-path'] + restrict_to_paths)

296

if restrict_to_repositories:

297

cmd.extend(['--restrict-to-repository'] + restrict_to_repositories)

298

if append_only:

299

cmd.append('--append-only')

300

if storage_quota:

301

cmd.extend(['--storage-quota', storage_quota])

302

303

subprocess.run(cmd, check=True)

304

```

305

306

Usage example:

307

```python

308

import subprocess

309

310

# Serve with path restrictions (typically in SSH authorized_keys)

311

# command="borg serve --restrict-to-path /backup/repos" ssh-rsa AAAA...

312

313

# Serve in append-only mode

314

# command="borg serve --append-only --restrict-to-path /backup/repo" ssh-rsa AAAA...

315

```

316

317

### Lock Management

318

319

Break repository and cache locks when operations are interrupted or stuck.

320

321

```python { .api }

322

def break_repository_lock(repo_path: str) -> None:

323

"""

324

Break repository and cache locks.

325

326

Args:

327

repo_path: Path to repository

328

329

Warning: Only use when no borg process is running

330

"""

331

cmd = ['borg', 'break-lock', repo_path]

332

subprocess.run(cmd, check=True)

333

```

334

335

Usage example:

336

```python

337

import subprocess

338

339

# Break locks when repository appears stuck

340

# WARNING: Ensure no other borg processes are running first!

341

subprocess.run(['borg', 'break-lock', '/backup/repo'], check=True)

342

```

343

344

## Types

345

346

```python { .api }

347

class PruneStats:

348

"""Pruning operation statistics"""

349

def __init__(self):

350

self.kept_archives: int # Number of archives kept

351

self.pruned_archives: int # Number of archives pruned

352

self.deleted_data: int # Bytes of data deleted

353

self.freed_space: int # Space freed in repository

354

355

class CompactionStats:

356

"""Repository compaction statistics"""

357

def __init__(self):

358

self.segments_before: int # Segments before compaction

359

self.segments_after: int # Segments after compaction

360

self.size_before: int # Size before compaction

361

self.size_after: int # Size after compaction

362

self.freed_space: int # Space freed by compaction

363

self.time_elapsed: float # Compaction time in seconds

364

365

class UpgradeInfo:

366

"""Repository upgrade information"""

367

def __init__(self):

368

self.version_before: str # Version before upgrade

369

self.version_after: str # Version after upgrade

370

self.tam_enabled: bool # TAM authentication enabled

371

self.changes_made: list # List of changes made

372

```