Compare commits
4 Commits
e6f5ee38e5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0086878d57 | ||
|
|
2ed9f3345d | ||
|
|
50dd0df84f | ||
|
|
e17894e49c |
67
README.md
67
README.md
@@ -2,52 +2,23 @@
|
|||||||
|
|
||||||
Purpose:
|
Purpose:
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> This behvior does not work on the `resticprofile` branch
|
|
||||||
|
|
||||||
- Wrap `restic` with the ability to start/stop Docker containers
|
- Wrap `restic` with the ability to start/stop Docker containers
|
||||||
- Send updates to Loki server
|
- Send updates to Loki server
|
||||||
|
|
||||||
## Installation
|
## Environment Variables
|
||||||
|
|
||||||
### Include in Repo
|
Put these in a `.env` file in the directory that the backup will be run from.
|
||||||
|
|
||||||
From a parent repo, add this one as a submodule:
|
| Env Variable | Description |
|
||||||
|
|---------------------|--------------------------------------------------------------------------------------------|
|
||||||
```shell
|
| `HOSTNAME` | Network hostname of where the backup is running. Used to tag the backups in restic |
|
||||||
git submodule add https://gitea.john-stream.com/john/restic-scripts
|
| `BACKUP_DIR` | Directory to back up |
|
||||||
```
|
| `RESTIC_REPOSITORY` | Directory for the restic repository. This is usually on a mount point made from Proxmox |
|
||||||
|
| `RESTIC_PASSWORD` | Password for the restic repository |
|
||||||
Then add this to the `docker-compose.yml` file of the parent.
|
| `LOKI_URL` | Push URL for Loki. Should include the port and end with something like `/loki/api/v1/push` |
|
||||||
|
|
||||||
```yaml
|
|
||||||
include:
|
|
||||||
- restic-scripts/docker-compose.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
Put these in `./restic-scripts/.env`, which is on the `.gitignore` list.
|
|
||||||
|
|
||||||
| Env Variable | Description |
|
|
||||||
| ------------------- | --------------------------------------------------------------------------------------- |
|
|
||||||
| `BACKUP_DIR` | Directory to back up |
|
|
||||||
| `RESTIC_REPOSITORY` | Directory for the restic repository. This is usually on a mount point made from Proxmox |
|
|
||||||
| `TZ` | Set to modify the timezone shown in the scheduler |
|
|
||||||
|
|
||||||
### Key file
|
|
||||||
|
|
||||||
The password needs to be stored in `./restic-scripts/key`. Make sure it has the right (secure) permissions.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo chown root:root ./restic-scripts/key && sudo chmod 600 ./restic-scripts/key
|
|
||||||
```
|
|
||||||
|
|
||||||
## Loki Updates
|
## Loki Updates
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> This doesn't currently work on the `resticprofile` branch
|
|
||||||
|
|
||||||
Updates sent to Loki will have the following labels:
|
Updates sent to Loki will have the following labels:
|
||||||
|
|
||||||
| Label | Description |
|
| Label | Description |
|
||||||
@@ -57,28 +28,16 @@ Updates sent to Loki will have the following labels:
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Check snapshots
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker compose exec backup resticprofile snapshots
|
python -m restic.snapshots
|
||||||
```
|
```
|
||||||
|
|
||||||
Dry-run a backup
|
To stop docker containers before the backup and start them again afterwards, use the `--project` and `--services` flags.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker compose exec backup resticprofile --dry-run backup
|
python -m restic.backup --tag manual --project joplin --services app,db
|
||||||
```
|
```
|
||||||
|
|
||||||
Check crontab entry in container
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker compose exec backup cat /var/spool/cron/crontabs/root
|
python -m restic.prune
|
||||||
```
|
|
||||||
|
|
||||||
### Crond
|
|
||||||
|
|
||||||
Crond command when scheduled using `resticprofile schedule --all`
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cd /resticprofile && /usr/bin/resticprofile --no-ansi --config /etc/resticprofile/profiles.yaml --name default backup
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
services:
|
|
||||||
backup:
|
|
||||||
image: creativeprojects/resticprofile
|
|
||||||
entrypoint: '/bin/sh'
|
|
||||||
command:
|
|
||||||
- -c
|
|
||||||
- 'resticprofile-schedule.sh && crond -f'
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
hostname: ${HOSTNAME}
|
|
||||||
volumes:
|
|
||||||
- ./restic-profile.yaml:/etc/resticprofile/profiles.yaml:ro
|
|
||||||
- ./resticprofile-schedule.sh:/usr/local/bin/resticprofile-schedule.sh:ro
|
|
||||||
- ./key:/etc/resticprofile/key:ro
|
|
||||||
- ${BACKUP_DIR}:${BACKUP_DIR}:ro
|
|
||||||
- ${RESTIC_REPOSITORY}:${RESTIC_REPOSITORY}:rw
|
|
||||||
@@ -12,4 +12,4 @@ authors = [
|
|||||||
license = { file = "LICENSE" }
|
license = { file = "LICENSE" }
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
dependencies = ["rich", "requests", "click"]
|
dependencies = ["rich", "requests", "click", "docker", "python-dotenv"]
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ ruff
|
|||||||
rich
|
rich
|
||||||
requests
|
requests
|
||||||
click
|
click
|
||||||
|
docker
|
||||||
|
python-dotenv
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
global:
|
|
||||||
scheduler: crond
|
|
||||||
|
|
||||||
default:
|
|
||||||
base-dir: ${BACKUP_DIR}
|
|
||||||
repository: local:${RESTIC_REPOSITORY}
|
|
||||||
password-file: key
|
|
||||||
initialize: true
|
|
||||||
backup:
|
|
||||||
source: ./
|
|
||||||
exclude-caches: true
|
|
||||||
one-file-system: true
|
|
||||||
schedule: "*:00"
|
|
||||||
schedule-permission: system
|
|
||||||
check-after: true
|
|
||||||
tag:
|
|
||||||
- resticprofile
|
|
||||||
|
|
||||||
retention:
|
|
||||||
after-backup: true
|
|
||||||
before-backup: false
|
|
||||||
prune: true
|
|
||||||
tag:
|
|
||||||
- resticprofile
|
|
||||||
keep-within: 3h
|
|
||||||
keep-hourly: 72
|
|
||||||
keep-daily: 14
|
|
||||||
keep-weekly: 8
|
|
||||||
keep-monthly: 6
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
resticprofile unschedule > /dev/null
|
|
||||||
|
|
||||||
resticprofile schedule --all
|
|
||||||
|
|
||||||
echo "Scheduled all restic profiles"
|
|
||||||
@@ -81,6 +81,7 @@ def main(
|
|||||||
logging.getLogger('urllib3.connectionpool').setLevel('WARNING')
|
logging.getLogger('urllib3.connectionpool').setLevel('WARNING')
|
||||||
|
|
||||||
if project is not None and services is not None:
|
if project is not None and services is not None:
|
||||||
|
logger.debug(f'Using project {project} and stopping services: {services}')
|
||||||
decorator = manage_containers(project=project, services=services.split(','))
|
decorator = manage_containers(project=project, services=services.split(','))
|
||||||
func = decorator(run)
|
func = decorator(run)
|
||||||
else:
|
else:
|
||||||
@@ -96,4 +97,10 @@ def main(
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
dotenv_file = Path.cwd() / '.env'
|
||||||
|
print(dotenv_file)
|
||||||
|
load_dotenv(dotenv_path=dotenv_file)
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ def manage_containers(project: str, services: list[str]):
|
|||||||
try:
|
try:
|
||||||
project_containers = (
|
project_containers = (
|
||||||
c
|
c
|
||||||
for c in client.containers.list()
|
for c in client.containers.list(all=True)
|
||||||
if c.labels['com.docker.compose.project'] == project
|
if c.labels.get('com.docker.compose.project', False)
|
||||||
)
|
)
|
||||||
service_dict: dict[str, Container] = {
|
service_dict: dict[str, Container] = {
|
||||||
c.labels['com.docker.compose.service']: c for c in project_containers
|
service: c for c in project_containers
|
||||||
|
if (service := c.labels.get('com.docker.compose.service', False))
|
||||||
}
|
}
|
||||||
containers: list[Container] = [service_dict[s] for s in services]
|
containers: list[Container] = [service_dict[s] for s in services]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -95,4 +95,7 @@ def main(loki_url: str, dry_run: bool, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -35,4 +35,7 @@ def main(loki_url: str = None):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user