Skip to content

Commit 7aab431

Browse files
committed
Initial release: backup and restore for macOS Docker media stacks
0 parents  commit 7aab431

11 files changed

Lines changed: 875 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Bug Report
2+
description: Something isn't working
3+
labels: ["bug"]
4+
body:
5+
- type: textarea
6+
id: description
7+
attributes:
8+
label: What happened?
9+
description: Describe the bug
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: expected
14+
attributes:
15+
label: What did you expect?
16+
validations:
17+
required: true
18+
- type: input
19+
id: macos-version
20+
attributes:
21+
label: macOS version
22+
placeholder: e.g. Sonoma 14.2
23+
validations:
24+
required: true
25+
- type: input
26+
id: chip
27+
attributes:
28+
label: Mac chip
29+
placeholder: e.g. M1, M2 Pro, M4
30+
validations:
31+
required: true
32+
- type: textarea
33+
id: logs
34+
attributes:
35+
label: Relevant logs
36+
description: Paste any error output or logs
37+
render: shell
38+
validations:
39+
required: false
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Feature Request
2+
description: Suggest a new feature or improvement
3+
labels: ["enhancement"]
4+
body:
5+
- type: textarea
6+
id: description
7+
attributes:
8+
label: What would you like?
9+
description: Describe the feature
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: why
14+
attributes:
15+
label: Why?
16+
description: What problem does this solve?
17+
validations:
18+
required: false

.github/workflows/validate.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Validate
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
validate:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout
12+
uses: actions/checkout@v4
13+
14+
- name: Validate shell scripts
15+
run: |
16+
bash -n backup.sh
17+
bash -n restore.sh
18+
bash -n install.sh

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.env
2+
config/
3+
logs/
4+
backups/

CONTRIBUTING.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Contributing
2+
3+
Thanks for your interest in contributing to Mac Media Stack Backup.
4+
5+
## How to Help
6+
7+
- **Bug reports**: Open an issue with your macOS version, Docker version, and the script output.
8+
- **Feature requests**: Open an issue describing what you'd like and why.
9+
- **Pull requests**: Fork the repo, make your changes on a branch, and open a PR. Keep changes focused on one thing.
10+
11+
## Guidelines
12+
13+
- Test your changes on a clean macOS install if possible.
14+
- Don't commit `.env` files, API keys, or any credentials.
15+
- Keep scripts compatible with both Intel and Apple Silicon Macs.
16+
- Match the existing code style (bash scripts use `set -e`, consistent formatting).
17+
18+
## Questions?
19+
20+
Open an issue. There are no dumb questions.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 liamvibecodes
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<div align="center">
2+
<br>
3+
<a href="#quick-start">
4+
<img src="https://img.shields.io/badge/MAC_MEDIA_STACK_BACKUP-00C853?style=for-the-badge&logo=apple&logoColor=white" alt="Mac Media Stack Backup" height="40" />
5+
</a>
6+
<br><br>
7+
<strong>Automated backup and restore for your *arr Docker stack on macOS</strong>
8+
<br>
9+
<sub>Your Sonarr database will corrupt eventually. Your config will vanish after a bad update.<br>This runs nightly so you never lose more than a day.</sub>
10+
<br><br>
11+
<img src="https://img.shields.io/badge/Docker-2496ED?style=flat-square&logo=docker&logoColor=white" />
12+
<img src="https://img.shields.io/badge/OrbStack-000000?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=&logoColor=white" />
13+
<img src="https://img.shields.io/badge/macOS-000000?style=flat-square&logo=apple&logoColor=white" />
14+
<img src="https://img.shields.io/badge/Bash-4EAA25?style=flat-square&logo=gnubash&logoColor=white" />
15+
<br><br>
16+
<img src="https://img.shields.io/github/stars/liamvibecodes/mac-media-stack-backup?style=flat-square&color=yellow" />
17+
<img src="https://img.shields.io/github/license/liamvibecodes/mac-media-stack-backup?style=flat-square" />
18+
<br><br>
19+
</div>
20+
21+
## Why Backup?
22+
23+
You will lose your Sonarr database at some point. A failed Docker update, a corrupt SQLite file, an accidental `docker compose down -v`. When it happens, you lose all your series, quality profiles, custom formats, indexer configs, and download history. Rebuilding takes hours.
24+
25+
This tool backs up configs, databases, and compose files every night. When something breaks, you restore in one command and you're back to where you were yesterday.
26+
27+
## What It Backs Up
28+
29+
| Item | Details |
30+
|------|---------|
31+
| **Config files** | config.xml, config.yml, settings.json, *.conf from each service |
32+
| **Databases** | All *.db files (Sonarr, Radarr, Prowlarr, Lidarr, Bazarr, etc.) |
33+
| **Compose file** | docker-compose.yml |
34+
| **Environment** | .env (sensitive values redacted) |
35+
| **Container state** | Snapshot of running containers at backup time |
36+
37+
Backups are compressed tarballs stored in `~/Media/backups/`. Old backups are pruned automatically (default: keep 14 days).
38+
39+
## Quick Start
40+
41+
```bash
42+
git clone https://github.com/liamvibecodes/mac-media-stack-backup.git
43+
cd mac-media-stack-backup
44+
bash backup.sh
45+
```
46+
47+
## Scheduled Backups
48+
49+
Install a nightly backup at 2am:
50+
51+
```bash
52+
bash install.sh
53+
```
54+
55+
Customize the schedule:
56+
57+
```bash
58+
bash install.sh --hour 3 # run at 3am instead
59+
```
60+
61+
Remove the scheduled backup:
62+
63+
```bash
64+
bash install.sh --uninstall
65+
```
66+
67+
## Restore
68+
69+
List available backups:
70+
71+
```bash
72+
bash restore.sh --list
73+
```
74+
75+
Restore the most recent backup:
76+
77+
```bash
78+
bash restore.sh --latest
79+
```
80+
81+
Restore a specific backup:
82+
83+
```bash
84+
bash restore.sh 20260222-020000
85+
```
86+
87+
The restore process stops your containers, copies configs and databases back, restarts everything, and runs a health check.
88+
89+
**Note:** .env values are redacted in backups for security. After restoring, check your .env file and re-add any secrets if needed.
90+
91+
## Custom Media Path
92+
93+
All scripts default to `~/Media`. Use `--path` for a different location:
94+
95+
```bash
96+
bash backup.sh --path /Volumes/External/Media
97+
bash restore.sh --latest --path /Volumes/External/Media
98+
```
99+
100+
## Works With
101+
102+
- [mac-media-stack](https://github.com/liamvibecodes/mac-media-stack) — One-command Plex + Sonarr + Radarr setup
103+
- [mac-media-stack-advanced](https://github.com/liamvibecodes/mac-media-stack-advanced) — Power-user setup with transcoding, quality profiles, and automation
104+
105+
## Author
106+
107+
Built by [@liamvibecodes](https://github.com/liamvibecodes)
108+
109+
## License
110+
111+
[MIT](LICENSE)

0 commit comments

Comments
 (0)