Compare commits
92 Commits
f2a9e660ed
...
feat-backu
| Author | SHA1 | Date | |
|---|---|---|---|
|
a31a07bd16
|
|||
|
54a951b96a
|
|||
|
e1379bc480
|
|||
|
037e0cab9b
|
|||
|
2655869814
|
|||
|
0e96b5030d
|
|||
|
a217c79e7d
|
|||
|
6a16ebf084
|
|||
|
2617aa2bd2
|
|||
|
b686e4da4d
|
|||
|
439c239ac8
|
|||
|
acf599f905
|
|||
|
eae4f5e27b
|
|||
|
4fbe9bd5de
|
|||
|
dcc4970b20
|
|||
|
2eac1362b5
|
|||
|
e3d8479397
|
|||
|
91c5eab236
|
|||
|
ca7f089fe6
|
|||
|
479e256b1e
|
|||
|
11e5b5752e
|
|||
|
392938d0fb
|
|||
|
2cc059104e
|
|||
|
d09a26b73a
|
|||
|
097676f569
|
|||
|
e878661cb3
|
|||
|
cb50c1c515
|
|||
|
33de71a087
|
|||
|
fbd5fa5faa
|
|||
|
faf7d58f78
|
|||
|
0a75378bbc
|
|||
|
bdd74bdf2e
|
|||
|
78bee84061
|
|||
|
7b81858af6
|
|||
|
08fda17561
|
|||
|
841bd38807
|
|||
|
fb1fd711c2
|
|||
|
ecf714eda7
|
|||
|
81f693938e
|
|||
|
10d67861a0
|
|||
|
3f5befb44d
|
|||
|
1b75ddaef2
|
|||
|
7d6ef77e64
|
|||
|
ae7c20a7aa
|
|||
|
67df03efca
|
|||
|
48bb8c9d33
|
|||
|
5b53cb30ac
|
|||
|
f2bc221663
|
|||
|
b41a50006b
|
|||
|
c2ea2cdb39
|
|||
|
7e67409393
|
|||
|
6882d61f8e
|
|||
|
47a63202b8
|
|||
|
af289f1e28
|
|||
|
b08f681c92
|
|||
|
8dfd061991
|
|||
|
306d4bf8d0
|
|||
|
dbd679aa8b
|
|||
|
47ed9c11c1
|
|||
|
f9ad08fd09
|
|||
|
4c7338f857
|
|||
|
a95da35389
|
|||
|
c74683cfe7
|
|||
|
9dff413867
|
|||
|
23a2bae7ec
|
|||
|
942bb7d999
|
|||
|
6ff7a7e3b4
|
|||
|
8ae28e64f4
|
|||
|
f7e8248cac
|
|||
|
2af9066dec
|
|||
|
e3b2e064c0
|
|||
|
380a54cb25
|
|||
|
d5078186e7
|
|||
|
57bb696e6e
|
|||
|
c6cc7d4c6c
|
|||
|
90abc6c833
|
|||
|
395203f236
|
|||
|
57cc639cc8
|
|||
|
1405a2364e
|
|||
|
b165899f25
|
|||
|
86147d0103
|
|||
|
2c9ade0a8e
|
|||
|
35c1f727f6
|
|||
|
b7d2fca2f2
|
|||
|
725c4c02cc
|
|||
|
328256c6be
|
|||
|
b08dc862c9
|
|||
|
0810c6c099
|
|||
|
dd6b34e983
|
|||
|
6fd6d76594
|
|||
|
61e2431975
|
|||
|
9a23e35126
|
@@ -1,5 +1,6 @@
|
||||
---
|
||||
exclude_paths:
|
||||
- ".ansible/"
|
||||
- ".gitea/"
|
||||
- "galaxy.roles/"
|
||||
- "Taskfile.yml"
|
||||
|
||||
4
.crushignore
Normal file
4
.crushignore
Normal file
@@ -0,0 +1,4 @@
|
||||
ansible-vault-password-file
|
||||
|
||||
*secrets.yml
|
||||
*secrets.toml
|
||||
@@ -6,14 +6,9 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[*.yml.j2]
|
||||
[*.{yml,yaml,yml.j2}]
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[Vagrantfile]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
50
.gitea/workflows/lint.yml
Normal file
50
.gitea/workflows/lint.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Linting
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
yamllint:
|
||||
name: YAML Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install yamllint
|
||||
run: pip install yamllint
|
||||
|
||||
- name: Run yamllint
|
||||
run: yamllint . --format colored
|
||||
|
||||
ansible-lint:
|
||||
name: Ansible Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip install ansible ansible-lint
|
||||
|
||||
# Создаем пустой vault password file если он указан в конфиге, но отсутствует
|
||||
- name: Fix vault issue
|
||||
run: |
|
||||
if grep -q "vault_password_file" ansible.cfg && [ ! -f ansible-vault-password-file ]; then
|
||||
echo "Creating empty vault password file for CI..."
|
||||
echo "foobar" > ansible-vault-password-file
|
||||
fi
|
||||
|
||||
- name: Run ansible-lint
|
||||
run: ansible-lint .
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@
|
||||
/ansible-vault-password-file
|
||||
/temp
|
||||
*.retry
|
||||
|
||||
__pycache__
|
||||
|
||||
25
.yamllint.yml
Normal file
25
.yamllint.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
extends: default
|
||||
|
||||
ignore:
|
||||
- ".ansible/"
|
||||
- "galaxy.roles/"
|
||||
|
||||
rules:
|
||||
# Правила, требуемые ansible-lint
|
||||
comments:
|
||||
min-spaces-from-content: 1
|
||||
comments-indentation: false
|
||||
braces:
|
||||
max-spaces-inside: 1
|
||||
octal-values:
|
||||
forbid-implicit-octal: true
|
||||
forbid-explicit-octal: true
|
||||
|
||||
# Дополнительные настройки (опционально)
|
||||
line-length:
|
||||
max: 120
|
||||
allow-non-breakable-words: true
|
||||
allow-non-breakable-inline-mappings: true
|
||||
document-start: disable # Не требовать --- в начале файла
|
||||
truthy:
|
||||
level: warning
|
||||
69
AGENTS.md
Normal file
69
AGENTS.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# AGENTS GUIDE
|
||||
|
||||
## Overview
|
||||
Ansible-based server automation for personal services. Playbooks provision Dockerized apps (e.g., gitea, authelia, homepage, miniflux, wakapi, memos) via per-app users, Caddy proxy, and Yandex Docker Registry. Secrets are managed with Ansible Vault.
|
||||
|
||||
## Project Layout
|
||||
- Playbooks: `playbook-*.yml` (per service), `playbook-all-*.yml` for grouped actions.
|
||||
- Inventory: `production.yml` (ungrouped host `server`).
|
||||
- Variables: `vars/*.yml` (app configs, images), secrets in `vars/secrets.yml` (vault-encrypted).
|
||||
- Roles: custom roles under `roles/` (e.g., `eget`, `owner`, `secrets`) plus galaxy roles fetched to `galaxy.roles/`.
|
||||
- Files/templates: service docker-compose and backup templates under `files/`, shared templates under `templates/`.
|
||||
- Scripts: helper Python scripts in `scripts/` (SMTP utilities) and `files/backups/backup-all.py`.
|
||||
- CI: `.gitea/workflows/lint.yml` runs yamllint and ansible-lint.
|
||||
- Hooks: `lefthook.yml` references local hooks in `/home/av/projects/private/git-hooks` (gitleaks, vault check).
|
||||
- Formatting: `.editorconfig` enforces LF, trailing newline, 4-space indent; YAML/Jinja use 2-space indent.
|
||||
|
||||
## Setup
|
||||
- Copy vault password sample: `cp ansible-vault-password-file.dist ansible-vault-password-file` (needed for ansible and CI).
|
||||
- Install galaxy roles: `ansible-galaxy role install --role-file requirements.yml --force` (or `task install-roles`).
|
||||
- Ensure `yq`, `task`, `ansible` installed per README requirements.
|
||||
|
||||
## Tasks (taskfile)
|
||||
- `task install-roles` — install galaxy roles into `galaxy.roles/`.
|
||||
- `task ssh` — SSH to target using inventory (`production.yml`).
|
||||
- `task btop` — run `btop` on remote.
|
||||
- `task encrypt|decrypt -- <files>` — ansible-vault helpers.
|
||||
- Authelia helpers:
|
||||
- `task authelia-cli -- <args>` — run authelia CLI in docker.
|
||||
- `task authelia-validate-config` — render `files/authelia/configuration.template.yml` with secrets and validate via authelia docker image.
|
||||
- `task authelia-gen-random-string LEN=64` — generate random string.
|
||||
- `task authelia-gen-secret-and-hash LEN=72` — generate hashed secret.
|
||||
- `task format-py-files` — run Black via docker (pyfound/black).
|
||||
|
||||
## Ansible Usage
|
||||
- Inventory: `production.yml` with `server` host. `ansible.cfg` points to `./ansible-vault-password-file` and `./galaxy.roles` for roles path.
|
||||
- Typical deploy example (from README): `ansible-playbook -i production.yml --diff playbook-gitea.yml`.
|
||||
- Per-app playbooks: `playbook-<app>.yml`; grouped runs: `playbook-all-setup.yml`, `playbook-all-applications.yml`, `playbook-upgrade.yml`, etc.
|
||||
- Secrets: encrypted `vars/secrets.yml`; additional `files/<app>/secrets.yml` used for templating (e.g., Authelia). Respect `.crushignore` ignoring vault files.
|
||||
- Templates: many `docker-compose.template.yml` and `*.template.sh` files under `files/*` plus shared `templates/env.j2`. Use `vars/*.yml` to supply values.
|
||||
- Custom roles:
|
||||
- `roles/eget`: installs `eget` tool; see defaults/vars for version/source.
|
||||
- `roles/owner`: manages user/group and env template.
|
||||
- `roles/secrets`: manages vault-related items.
|
||||
|
||||
## Linting & CI
|
||||
- Local lint configs: `.yamllint.yml`, `.ansible-lint.yml` (excludes `.ansible/`, `.gitea/`, `galaxy.roles/`, `Taskfile.yml`).
|
||||
- CI (.gitea/workflows/lint.yml) installs `yamllint` and `ansible-lint` and runs `yamllint .` then `ansible-lint .`; creates dummy vault file if missing.
|
||||
- Pre-commit via lefthook (local hooks path): runs `gitleaks git --staged` and secret-file vault check script.
|
||||
|
||||
## Coding/Templating Conventions
|
||||
- Indentation: 2 spaces for YAML/Jinja (`.editorconfig`), 4 spaces default elsewhere.
|
||||
- End-of-line: LF; ensure final newline.
|
||||
- Template suffixes `.template.yml`, `.yml.j2`, `.template.sh` are rendered via Ansible `template` module.
|
||||
- Avoid committing real secrets; `.crushignore` excludes `ansible-vault-password-file` and `*secrets.yml`.
|
||||
- Service directories under `files/` hold docker-compose and backup templates; ensure per-app users and registry settings align with `vars/*.yml`.
|
||||
|
||||
## Testing/Validation
|
||||
- YAML lint: `yamllint .` (CI default).
|
||||
- Ansible lint: `ansible-lint .` (CI default).
|
||||
- Authelia config validation: `task authelia-validate-config` (renders with secrets then validates via docker).
|
||||
- Black formatting for Python helpers: `task format-py-files`.
|
||||
- Python types validation with mypy: `mypy <file.py>`.
|
||||
|
||||
## Operational Notes
|
||||
- Deployments rely on `production.yml` inventory and per-app playbooks; run with `--diff` for visibility.
|
||||
- Yandex Docker Registry auth helper: `files/yandex-docker-registry-auth.sh`.
|
||||
- Backups: templates and scripts under `files/backups/` per service; `backup-all.py` orchestrates.
|
||||
- Home network/DNS reference in README (Yandex domains).
|
||||
- Ensure `ansible-vault-password-file` present for vault operations and CI.
|
||||
28
Taskfile.yml
28
Taskfile.yml
@@ -21,19 +21,19 @@ tasks:
|
||||
|
||||
ssh:
|
||||
cmds:
|
||||
- ssh {{.REMOTE_USER}}@{{.REMOTE_HOST}}
|
||||
- ssh {{.REMOTE_USER}}@{{.REMOTE_HOST}}
|
||||
|
||||
btop:
|
||||
cmds:
|
||||
- ssh {{.REMOTE_USER}}@{{.REMOTE_HOST}} -t btop
|
||||
- ssh {{.REMOTE_USER}}@{{.REMOTE_HOST}} -t btop
|
||||
|
||||
vars-decrypt:
|
||||
encrypt:
|
||||
cmds:
|
||||
- ansible-vault decrypt vars/vars.yml
|
||||
- ansible-vault encrypt {{.CLI_ARGS}}
|
||||
|
||||
vars-encrypt:
|
||||
decrypt:
|
||||
cmds:
|
||||
- ansible-vault encrypt vars/vars.yml
|
||||
- ansible-vault decrypt {{.CLI_ARGS}}
|
||||
|
||||
authelia-cli:
|
||||
cmds:
|
||||
@@ -55,18 +55,26 @@ tasks:
|
||||
validate-config --config /data/{{.DEST_FILE}}
|
||||
|
||||
authelia-gen-random-string:
|
||||
summary: |
|
||||
Generate random string.
|
||||
Usage example:
|
||||
task authelia-gen-random-string LEN=64
|
||||
vars:
|
||||
LEN: '{{ .LEN | default 10 }}'
|
||||
cmds:
|
||||
- >
|
||||
{{.AUTHELIA_DOCKER}}
|
||||
crypto rand --length 32 --charset alphanumeric
|
||||
crypto rand --length {{.LEN}} --charset alphanumeric
|
||||
|
||||
authelia-gen-secret-and-hash:
|
||||
vars:
|
||||
LEN: '{{ .LEN | default 72 }}'
|
||||
cmds:
|
||||
- >
|
||||
{{.AUTHELIA_DOCKER}}
|
||||
crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
|
||||
crypto hash generate pbkdf2 --variant sha512 --random --random.length {{.LEN}} --random.charset rfc3986
|
||||
|
||||
format-py-files:
|
||||
cmds:
|
||||
- >-
|
||||
docker run --rm -u {{.USER_ID}}:{{.GROUP_ID}} -v $PWD:/app -w /app pyfound/black:latest_release black .
|
||||
- >-
|
||||
docker run --rm -u {{.USER_ID}}:{{.GROUP_ID}} -v $PWD:/app -w /app pyfound/black:latest_release black .
|
||||
|
||||
10
files/authelia/backup.template.sh
Normal file
10
files/authelia/backup.template.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
echo "{{ app_name }}: backup data with gobackups"
|
||||
|
||||
(cd "{{ base_dir }}" && gobackup perform --config "{{ gobackup_config }}")
|
||||
|
||||
echo "{{ app_name }}: done."
|
||||
@@ -895,9 +895,9 @@ session:
|
||||
##
|
||||
## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness
|
||||
##
|
||||
# redis:
|
||||
# host: '127.0.0.1'
|
||||
# port: 6379
|
||||
redis:
|
||||
host: 'authelia_redis'
|
||||
port: 6379
|
||||
## Use a unix socket instead
|
||||
# host: '/var/run/redis/redis.sock'
|
||||
|
||||
@@ -1026,7 +1026,7 @@ storage:
|
||||
##
|
||||
local:
|
||||
## Path to the SQLite3 Database.
|
||||
path: '/config/authelia_storage.sqlite3'
|
||||
path: '/data/authelia_storage.sqlite3'
|
||||
|
||||
##
|
||||
## MySQL / MariaDB (Storage Provider)
|
||||
@@ -1292,7 +1292,8 @@ identity_providers:
|
||||
## configured has the RS256 algorithm. For RSA keys (RS or PS) the minimum is a 2048 bit key.
|
||||
jwks:
|
||||
-
|
||||
## Key ID embedded into the JWT header for key matching. Must be an alphanumeric string with 7 or less characters.
|
||||
## Key ID embedded into the JWT header for key matching.
|
||||
## Must be an alphanumeric string with 7 or less characters.
|
||||
## This value is automatically generated if not provided. It's recommended to not configure this.
|
||||
# key_id: 'example'
|
||||
|
||||
@@ -1399,6 +1400,24 @@ identity_providers:
|
||||
userinfo_signed_response_alg: 'none'
|
||||
token_endpoint_auth_method: 'client_secret_basic'
|
||||
|
||||
-
|
||||
client_name: 'Wakapi'
|
||||
client_id: '{{ oidc__wakapi__client_id }}'
|
||||
client_secret: '{{ oidc__wakapi__client_secret }}'
|
||||
redirect_uris:
|
||||
- 'https://wakapi.vakhrushev.me/oidc/authelia/callback'
|
||||
scopes:
|
||||
- 'openid'
|
||||
- 'profile'
|
||||
- 'email'
|
||||
# response_types:
|
||||
# - 'code'
|
||||
# grant_types:
|
||||
# - 'authorization_code'
|
||||
# access_token_signed_response_alg: 'none'
|
||||
# userinfo_signed_response_alg: 'none'
|
||||
# token_endpoint_auth_method: 'client_secret_basic'
|
||||
|
||||
-
|
||||
## The description to show to users when they end up on the consent screen. Defaults to the ID above.
|
||||
client_name: 'Outline'
|
||||
|
||||
26
files/authelia/docker-compose.template.yml
Normal file
26
files/authelia/docker-compose.template.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
|
||||
authelia_app:
|
||||
container_name: 'authelia_app'
|
||||
image: 'docker.io/authelia/authelia:4.39.14'
|
||||
user: '{{ user_create_result.uid }}:{{ user_create_result.group }}'
|
||||
restart: 'unless-stopped'
|
||||
networks:
|
||||
- "web_proxy_network"
|
||||
- "monitoring_network"
|
||||
volumes:
|
||||
- "{{ config_dir }}:/config"
|
||||
- "{{ data_dir }}:/data"
|
||||
|
||||
authelia_redis:
|
||||
image: valkey/valkey:9.0-alpine
|
||||
container_name: authelia_redis
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- "monitoring_network"
|
||||
|
||||
networks:
|
||||
web_proxy_network:
|
||||
external: true
|
||||
monitoring_network:
|
||||
external: true
|
||||
@@ -1,15 +0,0 @@
|
||||
services:
|
||||
|
||||
authelia_app:
|
||||
container_name: 'authelia_app'
|
||||
image: 'docker.io/authelia/authelia:4.39.13'
|
||||
user: '{{ user_create_result.uid }}:{{ user_create_result.group }}'
|
||||
restart: 'unless-stopped'
|
||||
networks:
|
||||
- "web_proxy_network"
|
||||
volumes:
|
||||
- "{{ config_dir }}:/config"
|
||||
|
||||
networks:
|
||||
web_proxy_network:
|
||||
external: true
|
||||
16
files/authelia/gobackup.template.yml
Normal file
16
files/authelia/gobackup.template.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
# https://gobackup.github.io/configuration
|
||||
|
||||
models:
|
||||
|
||||
authelia:
|
||||
compress_with:
|
||||
type: 'tgz'
|
||||
storages:
|
||||
local:
|
||||
type: 'local'
|
||||
path: '{{ backups_dir }}'
|
||||
keep: 3
|
||||
databases:
|
||||
users:
|
||||
type: sqlite
|
||||
path: "{{ (data_dir, 'authelia_storage.sqlite3') | path_join }}"
|
||||
@@ -1,136 +1,147 @@
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
37373465363866623436393966626530656465653837363463323664383666663164363233623738
|
||||
3233383234343332623065386134643161346132653431350a303935373631656366633339663333
|
||||
32353263346437626633346263323533313238613462613334353334643236343438306630333037
|
||||
6435313930313262310a386662336637623461303636633337303531353261343861313966383764
|
||||
32353439333364353434653164666434326232383562363063313433373137383138396266383134
|
||||
36613538653531346232353236313262313138656234626638623034363436303337313961333536
|
||||
66366666383363333439333439623931626662383764393463663733333034636633353538656137
|
||||
62386263613533343963396166666532313862366433636536613266353064633932323765336362
|
||||
34643634643962333563346633306665313765393663306364363362333536646635343832333634
|
||||
30383361653063396333616433323235663338346439303465323135626639646166303164643339
|
||||
31616534633034393339373934346531633433323433646436333863306566356462613531663136
|
||||
61343561616434306163616130626338663737633866646537323263316636626137366361363963
|
||||
31303361366365616335363230343239663038623830303232376236393639663232333764643064
|
||||
34666439316430356664313531333363626562633636326463313765343263393636333465386339
|
||||
33623037343134633535303863626564373630656463336330396336303462373735346331616663
|
||||
63666161356565643539343431386231396162323030383836366161303634626266663934356362
|
||||
61623833613734333661613338373663663230363331373236323166636534613962613763343663
|
||||
31666534303965333466653335646263343764346465373461326166666266303138363933653566
|
||||
37636530306632346636626336616536346236663664383864623863653835366133633635613861
|
||||
63303634333962343039646564353534313063383434386462366333386331303433366665623734
|
||||
61353039313762383664626330663230656237373061616132376564323763393632356665306633
|
||||
34643865333165616664376162306634366532386437383461396163376366363832363834356164
|
||||
64376637373135383539353636346461353761366561303530326363366238393932333039313264
|
||||
34316539626365306461323336396631633532306637306331373863613531656565366236656338
|
||||
30306237626561613561353265643137353965313033313939643161613163643566663632663964
|
||||
61623134656238363134626530363933623930346532336366393163363562386265626233393139
|
||||
63633333313531666335376538613765663933626533636137306564616333373766613665613332
|
||||
65643331626361626136623432346233633364343963653932306632646436626433653337326665
|
||||
39343033353030616630663865613630613032333831626538323461383264636633623439393765
|
||||
65343866323237386336613764386439313830646239613135636161333138646664666339626137
|
||||
36616433393339346139323333363030613731313236636464393864616135346234643664343533
|
||||
31396661306664343031393865306533373762663962623730313261353231363661306134623934
|
||||
64613931356164386431663536363361386566353361333861666365636564643536306638376238
|
||||
37633865303063643962346664346366346362313463386432376637663934363165343537323532
|
||||
63363431623663656163316662343435636165306134373839613731326139636337343862326338
|
||||
61326433343631343065303735663434316330303139303834316137663330363762666664393062
|
||||
30653236636538396234313735613365386635323062666236656164633136313362643834336339
|
||||
32623834343334613839313138313462376237666238636663343333643533643537376261666433
|
||||
64323933323134393461623034623563316135333566326135326434613237363830623063626535
|
||||
66323533356366346130626530633337393263663664353430646330353339313534396434653137
|
||||
36663737396261653162663337663338373433653233616363626130333833323533303363643730
|
||||
66613135633761346433626164643130353963313762643361306537653639373934333565373439
|
||||
31636133383866373032373562653933316163353936386339326266363233663633623437346665
|
||||
66393630346434356563393039626537336537313930393437663562303031626338616266363361
|
||||
65653033363539633364326531653563383634303830386362303665306438663035373831646562
|
||||
30356564623733623939663332393463663730643533666134636361316263633166626566333831
|
||||
66376461383139626230343136373437393464646331633139633435303236623132343035373037
|
||||
39363131623330376262326235646633303232623139626239326361313236316665316464616265
|
||||
35303166333561626130323864363430663332306338353731383139386131346132653632633132
|
||||
37643865393462623831623435633838323664666264623232326561653866626437373864666232
|
||||
64393466326162323236353539326364336238643031313434346566316434383733663663356334
|
||||
62343337386532393236353432653239643735323531306337373739343839306264356666636635
|
||||
35626665646634653766323939633434303238633564613962643364356631623539623032363039
|
||||
31336535333763323236633531616661313834636231363362376661313931623131343364356364
|
||||
35653539393265323636303930633639316139643631386632646139643266303531653865623664
|
||||
31303930613561323330356337396138633033616265356137353336613638656161633063663964
|
||||
33373965383532656634333863643131333461376135646635323035316230393439386130663036
|
||||
37373331356364343433316435666130373031303038643063313131653835333365366138656238
|
||||
38643437376234316332306434633039346564643863656461353364346335353839303734366565
|
||||
32613364356532623231623632363637373664393764636262346264383134366439373238623032
|
||||
62326163306532356262393565373937316530623963313266373736356632313831313465666663
|
||||
61303962333836373832383236663532376130316465393039326366636133323233316134646430
|
||||
63313437663662353962633561643535396332303533343962643038393165373239336431336664
|
||||
65356663393565383263613530663762643731356463653538316439303863643363303261363838
|
||||
33353739306337326665393164366232393665363465343537373866396136346164333663393738
|
||||
31316335366238316537386236393461656266323566636364343139393665616138663432333564
|
||||
37653837646666376530373530636164343633653162343131373034633432333138613138346339
|
||||
32303332626338653561323835343266353633613434346465616162326162393733643837663230
|
||||
62333630333464633362656661336139393639623863343036636534323637336561333734373262
|
||||
36373365306531383830383361303566626239343062316166303636323539373966626336613638
|
||||
31623863643632653036323834346362663834666431643637666137376139386666643834323465
|
||||
63626264643337376663633335666631653637626364653866353131393336303937633430366430
|
||||
38383066313831346461643862333838386566613661623130313038386137323331373434363033
|
||||
34613537303134343532643430383532353934623066383530653435626566333239333162316435
|
||||
30386361346336666665656336646633353663376337326131663435636533646162616332306530
|
||||
30373263376437646639623039343234393537303931346461643966383732336366363331643135
|
||||
65383462353034643464366334636136373035313437366639336338366133663765313735353366
|
||||
62386239326134343761313464383239316465633932363862303536353365376338643863643834
|
||||
32633233336262626336383061316137646431353766303930336562386136383530613538383837
|
||||
66336235643437636138646663393565383466636232366133343232306563363635316561346565
|
||||
36633637303163303963396132653731663134666238363939666663303033316564356364633162
|
||||
31376233306138666131333634336639643163666562653934336162323964613863646564616361
|
||||
33666264303163326664633839303562333664383130356134383836313635376239353137313363
|
||||
66613132663137383737373530326131663861303935663635373464306334363962333566663261
|
||||
64616361366137626163626139333630653331383763353632396130306231376662666363353962
|
||||
66343064313932386631303663373432646135353438313632316634336235316139313237666362
|
||||
31383638393362663038363765303634363366326265643332393165643635643339343137373930
|
||||
37633031626365353033333938623466663963376366353561303166373164386132376365643630
|
||||
32333134316464643564373537643734353534366563666435663663616331383039393862613838
|
||||
63633962316533386337366263636265646334636235323430383832363964343939633264343338
|
||||
64366539383831373636343330356537323662666533323935646634363466663239663362326531
|
||||
66363863383762303539373636336330353834303239376330623964393439356130646166663332
|
||||
65326162336366363466646230656362653531386162356235326235333866373966636434326537
|
||||
38653139393563373337346636333337373039343439343139313366316264613763663664633037
|
||||
32313237653239643635393363316465346561613331623033323137653865396239633639323534
|
||||
61326262643365363737393031383461626530636266393836663937666135363662353665376362
|
||||
63643039373931316439303731663762393237623065643236303737643966393836646335626132
|
||||
36376665656662373437653933356330636638626162666564393636633630663562303839326662
|
||||
35626261616534386361373539633636356136616137323737393466633364653730356138343638
|
||||
36663537663361393566616365383161366236646630653737643765666638346531376136643163
|
||||
37643530373330353238323431343761653633306464643835343333623837313135303031666535
|
||||
30326538636432303363666131376334393361333232313834623230306630373834633265333237
|
||||
34323731333835363863643031346166636464653731636636313161643265613861336638313338
|
||||
32383438353763343933383537636464666466386131363566306562333136356538326239656232
|
||||
33343631613134616265393232613063643561633335323665383133313536313364343066366665
|
||||
63636439376436393162306638303062616435333039343566613961626434303766616535623364
|
||||
32643866393430303137366264306262643365663034613965666332313430366630653736303537
|
||||
39663832326132393066373166613161613130363033363633366563353461663435393565326362
|
||||
37616462393933303937643664343663373234663066633834626164303866323835363333366266
|
||||
36356133336165613032646436306162663534306239313330353935336332643637653534626233
|
||||
38303965646361316434343131653461353234396163613736333235656639326231353734636266
|
||||
61613566336437666265366637336363326266383666383165343661333766303830633633393664
|
||||
34613061396564616337643032666561633038663062336233666263306132663139396565323035
|
||||
33353438633338363263313630393239376162366461383265386633613939663461616233396334
|
||||
35616433663862616530636362396333343464393339396538333861303763393066626439396361
|
||||
32303732393062383662633937653531653933333463366638613035333832636235346233653866
|
||||
35656664636636326163353439626538343463613465613634656530366566323165623162303565
|
||||
31303139343138616132383731323061346431336133643735356532373838663761313139663361
|
||||
33656365636261303532333131346633373732643232303139353431663132346532616334613034
|
||||
30363137613133396335343162643936623330393834356365663932626262313366616534663033
|
||||
37376132656233633361623733356334636266383361656437613331306636656333623139303661
|
||||
38353639346266333833663533366661633136313262396465633738373438623262306637643336
|
||||
34656136343139663461336264346666333537633065343766316630626566363761396537643334
|
||||
30323766633664666639363965363138396334343365346333663035323839613030626533303830
|
||||
31333734386565383831373939306265636432386332313531623638333663643162623339613366
|
||||
34363935636266313736366639373833636230633661323935646331376336623937353039343561
|
||||
39623865663462663431643738653663663733663765383663623437383163613232336332653531
|
||||
64663133353934313436336633666435343162316135303663636130353936363936363032313263
|
||||
65376436316237663434323736663263376164346139616465663737323963316361373438633339
|
||||
31323261343635633338613636643232616537653331326331353161396331633461643861323466
|
||||
64633033623537386263376263346666633939336133616234363964363339616331636464326163
|
||||
63633862373030323132613439343431333938343864383637613435323732356234613965666364
|
||||
37343765353735633737393664306533633262353562323565306537646534663833343430643662
|
||||
39326134353335653938396532363136376332306162613836663464636233383436333735663731
|
||||
313461396466396230323561646662653063
|
||||
65666236353432623164363161633732363265343935316466326332323638626138633130666663
|
||||
3566393731353063393466663831623537393939663838640a303935383565376430646431613464
|
||||
66363161373765663665316433393835323236363561663633623533363166323533623137646437
|
||||
3438383538613832660a373337323633666535656439383438653132646235623834643730323762
|
||||
64656336323037653937393836623061343563303337633830346164613731633761376138313666
|
||||
33343265343830306139386164353861633230326333616539313032323935313435623762316163
|
||||
63353535663533656166333034636462663266343061626637613830313962333531396339393334
|
||||
39336233623462303137343264373631396464303038346131633333333033343839393438653330
|
||||
61646166313762633333353233366430333764646261356438336532653463646264643562346262
|
||||
32653339353861653964663935393638656563373239633234656131633133643366653833376233
|
||||
34643033393039616363656330323765346336643664393934376138353266303731613066626231
|
||||
30313362663430343337663663373132383831333662353034316134623639393938306237396230
|
||||
65633565643861366434336135313465623537616166356637346137323566333239376361633930
|
||||
66356664633433306134613166353032363234633961623862646537376365383535623033356639
|
||||
34336433646430323630313464333631663739343832316362666165623039313535306433643761
|
||||
61376264616462333839326233613764333633643233663236666562306666353934323636353262
|
||||
32386333623632326332373438373236646138326537343835383766663463643535383534633633
|
||||
34343166343362343165333837313362666533353939336533326138386538323961323530626663
|
||||
63633334663561396565656662363830656133323364383536346163316333356661643261633635
|
||||
37323536653664613564616466633631616465656266373830373964326566623733396130303031
|
||||
31663166323863353565353235323235363161366534663539343338633434626232336261356438
|
||||
38373339383361356565366436376266336234356436363562623431666436626562353065356230
|
||||
37333737623161303431393461383438643137613962613838386537663564646333356538393337
|
||||
34373136343361333738396664616436363066323030306438666437333839653336316264343139
|
||||
38656234623363386561393961363262316535373232353132616136633339613533633333376235
|
||||
35656632643363386133656438616366643630303337383130386330326532623930346561383739
|
||||
65636138313566363539323663303631663862323034313062353633646638633463653263333035
|
||||
66646539393639643834353966396132343437666435626537633336393864326630623961303338
|
||||
36616663383262363138346331386239653634373135616232656462353562373939356631633433
|
||||
64356461653336353039643065663538373363666339363231373762363163653762363832373238
|
||||
37386638373261383533633937613561613961353765363864613031356334303138613766383631
|
||||
36666433636663343931643462383338613662333233666337363038666531633864333436383737
|
||||
36363562323936313764386336656639633638643465636131373532313238376565353933336133
|
||||
37663961623937336230636466643531316463323733626134663331323135396637323231383231
|
||||
33643736316537646264353662643261666165366562393031613565623630336333353961353661
|
||||
62633362613863303936623436616136616139363861653233313865343532366465373937306139
|
||||
61316665653234363033396566316331316164346461353438633864333334653730333065376631
|
||||
66616238663062666139653062383036636366646364346632396239623233356533343038363733
|
||||
33316165306130616665326364616231613830313334383961633333303261656131333161323237
|
||||
38616435633334646533653830393739336363653664373235363863396262623736626435313735
|
||||
39353065643033343062616137346361646136313265653965313133666130393361306430303638
|
||||
64643364663335343961373865653564366362396138626531613232313461376463336437336666
|
||||
30373766666231646264356663626335393233333465386164313630613137303066336430653662
|
||||
35336531633039633938363430363239653065356230313538323630316561643033623833656164
|
||||
65366435653063616361366666373561663538373363346264386331316531376262663663383266
|
||||
38346163653439366430656536666631366534663163396230353531396335663638386261613832
|
||||
31336339336465393333383761623663383563613930663430626166666635393164366562663063
|
||||
34323031333939656161643139386532666361663630346632383333373261326134636564393233
|
||||
38363630633435353730383234663536623166373533333639353963613665353339383837626138
|
||||
38653730316538626662303636363664613566383033323661363533333032306362346562316464
|
||||
36303730666531396531386331653466396233623138393763653965323239393237636237303237
|
||||
66323366343036643765646539366261613062646532306265353430636332386330613962666131
|
||||
33383063343638616338326533646162306438616434316139313433303636366665336364656534
|
||||
66353634646563373463633637383766343332346530653033663937613135363233386138306565
|
||||
39386262663939346432383134333661623637396162623336626137316166613035333138653632
|
||||
34653364333732366231396637353939653262323934366333373130613932366533346632366164
|
||||
31313663303034306436393763323361616434306134336231383639346261376439643162643539
|
||||
35323534366435393531613665333337633365353831326534363737396463363666316639373233
|
||||
38386431336631363831366261373439376231326465323736356331636136393762383331336265
|
||||
64356363336639356361326539396234626566653334656561386431616139323433376563303132
|
||||
32363864663062643065643534623933653165636264653461303262313662663165616463353965
|
||||
36613134343634393066613533343362393137356464303530653964363031653231663962303037
|
||||
38633730633766306264613865373736346661623531616563316232393235643931353663383066
|
||||
39386633383930383732343266326161303663646636383735646332623661303433366161363635
|
||||
31313839396539343063613166616134636134333639363362343566356435663934646263653061
|
||||
31616137363031333561656134396534333430613637376465363633663861666262616137336337
|
||||
38396639333465316431303433653338653338303031313566633330656535666531316235393138
|
||||
64383332323466653065343765346162343532386438326362626637656130613433393339323564
|
||||
39633262393336383932306632636563313663336337653164306434393661663265306638636265
|
||||
37326335616666393262356663326665663561633038333237363234303838636135653861373032
|
||||
62643332376364386537326336663531613164376261653938333165656632613434343063613565
|
||||
62623262303632633335303430343164343433646238366137623030323233303661373434666234
|
||||
62626265623239343634363732623739383536646132656564313032663061383939616162366538
|
||||
61373738626362386265623739333139613531373738333862396430356635626130663633666439
|
||||
63333836346364313262613331656531623831646165313036393138636162336138613365396331
|
||||
63323333366232326365333965363734396565343334613733396437393932616637313738633765
|
||||
61373437313636666566303032343366376166643864333639326564363935623534386164346365
|
||||
65373538303765386337383964303937343038663832326665356666646336633835653530396337
|
||||
63316631333231623861373330303033396138613834623265633263653061623132366235336661
|
||||
31376633396534613161663462343365653262383133636238613166343366653464636137353165
|
||||
33623539366339353064373238663838303237343737376131306532333134313561323234336530
|
||||
64653335653262613738623335343361386261633636616663393035633066653735346431643663
|
||||
63626331633337363231313835376239636136633262393463643539343333373139616330373634
|
||||
63366439383232363165356166656664633133313533353236393637386535616536613630616137
|
||||
37316538653839353932363264663934613936346661343835333666303536363332363234653262
|
||||
33303530343764316462336634613661663532393864626437353764656564343435613131663339
|
||||
31616236376563623762326566333933303432646465613138373733363263346337633165616563
|
||||
61613836363231333966336165393961313930313934323536333334363763393438636138396361
|
||||
61373264626531393165376538336533303861643663333439653732313337613362346162373931
|
||||
35333330653531623134396134333938616538666661363737633639643462313034356531633033
|
||||
37613834356563303639356134323231646461356262636237323061386339306462343035336164
|
||||
63376664386663306135333635323030396639326639656131333564353265316631336261373562
|
||||
35663639306361373433633530616162636434373533333263303936343539386439303130366439
|
||||
37656263363839363339333236333835386537343232636461343338356234616332383330373161
|
||||
66646533393037353030616264623461626339613538306133393337623264326535343836363165
|
||||
39626263396162336434323437323133653735663136616266376331633665626234386131393433
|
||||
34663236623636656237666531353763333861646264646538313964663130353836396236336564
|
||||
31333132396535653064366430306464363634633032383666313738396265343335663664613662
|
||||
34626331303834346637383932633832343962666633323838383132323239363965313139373762
|
||||
36306266313337393235303834356435336138373437306661636535333836396366386336613937
|
||||
37386136623965373439373433353264393363653534306662316132643761353138303538353037
|
||||
62316636323338353633313461346161343461613465653463393931363661336638346435666134
|
||||
38303533633530383466623766393138653564373065373261656165313763663361373235356531
|
||||
66346663343636633961656639316365396265303632626465666532313338373336376135366138
|
||||
61303865356436616139373064393939356364623461316266316537363963396263613562613363
|
||||
37386466633934623062333634303335646232613039633839336365613634613561373436393733
|
||||
61316162623063636365346236323164333933643662366463313138623561633533653932663065
|
||||
64363734636663613831663630666432396237303630623234376432316532626165373464333134
|
||||
30646433646438373961333230343430383232316431313465646136643139353937313761333731
|
||||
66653335343935636530393361306162616232333935393135623235626238323238303339643863
|
||||
35373366353365613965656562633633303330383631383736306535366137393638313330343636
|
||||
35383039313866303239623564666461633161373231303534313466353137643666396133363265
|
||||
36373133323162666363303862313566613132333739333164663166666565303032306633636632
|
||||
63366539353663666162633832373264306135646266656563373433376438616530626530393131
|
||||
36376630306539303865613639643538333134666533643261356662386433626265613431613334
|
||||
35353634663930653537326666653763393831363637613639653862323730633266323234656662
|
||||
35666433623739323435626536303561386332313838383432303437633731666435393331353139
|
||||
32376638343939626237346363623236653639356234633366323464663763366339663536386162
|
||||
62623831336165393630363263396466643563383330353232373435613364316538613835313332
|
||||
30623136316437333462333864663164356539656436666539313536653065346337353565656138
|
||||
30663737333035336137313034626339613631396237326163366364366634346438643831376166
|
||||
33616238643033313662353031306534666161636133653531303932633231326139326161356564
|
||||
65323231663562323430633561363838663030346432313930323165313835616230663463316161
|
||||
63326364376461643035333564643964303030306131396233333439393131336435323134663064
|
||||
31306162383766333636386633393863663035376562633965666635353939653936626631346534
|
||||
64656462393335653332646562373361613132643034653536303435343833626433613137346232
|
||||
65643465323733336162366261336636326136616532343939613363663537336365363966373437
|
||||
62626566303435356237333238353736383262313933656139326634663934343864373131646461
|
||||
62653662336162313739663961636430346130666130646364393034636464616362636533353262
|
||||
62346162386561363239666232306432646336346434636335366638633762666634623737663866
|
||||
32343339646330353837323665626430646432316163656361323139633336646363643434363731
|
||||
36616534663330376333623631313332616462383936316238363032363762356531393332343430
|
||||
34613735633732333762306331666332316265333962343935613936613438353164623031346432
|
||||
66396264366666383835333538616430326161653839663838313764663664316266623762653463
|
||||
31383235326363646234306636636564366238663965663331623965373139353064363733363339
|
||||
34383937303033386566633939366331353333373935353263376235623430336236396135303233
|
||||
61666434613136396338656334306463666535373364373130343161373866333339333436643036
|
||||
64346162353530353334343438623835363664396265353762663832303366623735636238313039
|
||||
37353136626563393231353662633031343435636261616131323833613062643834663634353537
|
||||
30343430396135363466346236373462356366643539363665373663363932316163346665663935
|
||||
61343434303039623139323265623538366563373633623065353862303935393434663566303232
|
||||
37653033343230613766306334316464666533326566386633363835373466326263323861636635
|
||||
36396437373161346636616664313734343565643330376431633238396462633764386531313165
|
||||
62666538353239396361653035393636633263613639623038383734326564346261666335383234
|
||||
36333663303365313066616533333336306639363239663339313766356431316562353836303464
|
||||
3534373436363831616163383134383266636130316433633635
|
||||
|
||||
488
files/backups/backup-all.py
Normal file
488
files/backups/backup-all.py
Normal file
@@ -0,0 +1,488 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Backup script for all applications
|
||||
Automatically discovers and runs backup scripts for all users,
|
||||
then creates restic backups and sends notifications.
|
||||
"""
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import logging
|
||||
import pwd
|
||||
from abc import ABC
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Any
|
||||
import requests
|
||||
import tomllib
|
||||
|
||||
# Default config path
|
||||
CONFIG_PATH = Path("/etc/backup/config.toml")
|
||||
|
||||
# File name to store directories and files to back up
|
||||
BACKUP_TARGETS_FILE = "backup-targets"
|
||||
|
||||
# Default directory fo backups (relative to app dir)
|
||||
# Used when backup-targets file not exists
|
||||
BACKUP_DEFAULT_DIR = "backups"
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.StreamHandler(sys.stdout),
|
||||
logging.FileHandler("/var/log/backup-all.log"),
|
||||
],
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Config:
|
||||
host_name: str
|
||||
roots: List[Path]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Application:
|
||||
path: Path
|
||||
owner: str
|
||||
|
||||
|
||||
class Storage(ABC):
|
||||
def backup(self, backup_dirs: List[str]) -> bool:
|
||||
"""Backup directories"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class ResticStorage(Storage):
|
||||
TYPE_NAME = "restic"
|
||||
|
||||
def __init__(self, name: str, params: Dict[str, Any]):
|
||||
self.name = name
|
||||
self.restic_repository = str(params.get("restic_repository", ""))
|
||||
self.restic_password = str(params.get("restic_password", ""))
|
||||
self.aws_access_key_id = str(params.get("aws_access_key_id", ""))
|
||||
self.aws_secret_access_key = str(params.get("aws_secret_access_key", ""))
|
||||
self.aws_default_region = str(params.get("aws_default_region", ""))
|
||||
|
||||
if not all(
|
||||
[
|
||||
self.restic_repository,
|
||||
self.restic_password,
|
||||
self.aws_access_key_id,
|
||||
self.aws_secret_access_key,
|
||||
self.aws_default_region,
|
||||
]
|
||||
):
|
||||
raise ValueError(
|
||||
f"Missing storage configuration values for backend ResticStorage: '{self.name}'"
|
||||
)
|
||||
|
||||
def backup(self, backup_dirs: List[str]) -> bool:
|
||||
if not backup_dirs:
|
||||
logger.warning("No backup directories found")
|
||||
return True
|
||||
try:
|
||||
return self.__backup_internal(backup_dirs)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("Restic backup process failed: %s", exc)
|
||||
return False
|
||||
|
||||
def __backup_internal(self, backup_dirs: List[str]) -> bool:
|
||||
logger.info("Starting restic backup")
|
||||
logger.info("Destination: %s", self.restic_repository)
|
||||
|
||||
env = os.environ.copy()
|
||||
env.update(
|
||||
{
|
||||
"RESTIC_REPOSITORY": self.restic_repository,
|
||||
"RESTIC_PASSWORD": self.restic_password,
|
||||
"AWS_ACCESS_KEY_ID": self.aws_access_key_id,
|
||||
"AWS_SECRET_ACCESS_KEY": self.aws_secret_access_key,
|
||||
"AWS_DEFAULT_REGION": self.aws_default_region,
|
||||
}
|
||||
)
|
||||
|
||||
backup_cmd = ["restic", "backup", "--verbose"] + backup_dirs
|
||||
result = subprocess.run(backup_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.error("Restic backup failed: %s", result.stderr)
|
||||
return False
|
||||
|
||||
logger.info("Restic backup completed successfully")
|
||||
|
||||
check_cmd = ["restic", "check"]
|
||||
result = subprocess.run(check_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.error("Restic check failed: %s", result.stderr)
|
||||
return False
|
||||
|
||||
logger.info("Restic check completed successfully")
|
||||
|
||||
forget_cmd = [
|
||||
"restic",
|
||||
"forget",
|
||||
"--compact",
|
||||
"--prune",
|
||||
"--keep-daily",
|
||||
"90",
|
||||
"--keep-monthly",
|
||||
"36",
|
||||
]
|
||||
result = subprocess.run(forget_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.error("Restic forget/prune failed: %s", result.stderr)
|
||||
return False
|
||||
|
||||
logger.info("Restic forget/prune completed successfully")
|
||||
|
||||
result = subprocess.run(check_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.error("Final restic check failed: %s", result.stderr)
|
||||
return False
|
||||
|
||||
logger.info("Final restic check completed successfully")
|
||||
return True
|
||||
|
||||
|
||||
class Notifier(ABC):
|
||||
def send(self, html_message: str):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class TelegramNotifier(Notifier):
|
||||
TYPE_NAME = "telegram"
|
||||
|
||||
def __init__(self, name: str, params: Dict[str, Any]):
|
||||
self.name = name
|
||||
self.telegram_bot_token = str(params.get("telegram_bot_token", ""))
|
||||
self.telegram_chat_id = str(params.get("telegram_chat_id", ""))
|
||||
if not all(
|
||||
[
|
||||
self.telegram_bot_token,
|
||||
self.telegram_chat_id,
|
||||
]
|
||||
):
|
||||
raise ValueError(
|
||||
f"Missing notification configuration values for backend {name}"
|
||||
)
|
||||
|
||||
def send(self, html_message: str):
|
||||
url = f"https://api.telegram.org/bot{self.telegram_bot_token}/sendMessage"
|
||||
data = {
|
||||
"chat_id": self.telegram_chat_id,
|
||||
"parse_mode": "HTML",
|
||||
"text": html_message,
|
||||
}
|
||||
|
||||
response = requests.post(url, data=data, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
logger.info("Telegram notification sent successfully")
|
||||
else:
|
||||
logger.error(
|
||||
f"Failed to send Telegram notification: {response.status_code} - {response.text}"
|
||||
)
|
||||
|
||||
|
||||
class BackupManager:
|
||||
def __init__(
|
||||
self,
|
||||
config: Config,
|
||||
roots: List[Path],
|
||||
storages: List[Storage],
|
||||
notifiers: List[Notifier],
|
||||
):
|
||||
self.errors: List[str] = []
|
||||
self.warnings: List[str] = []
|
||||
self.successful_backups: List[str] = []
|
||||
self.config = config
|
||||
self.roots: List[Path] = roots
|
||||
self.storages = storages
|
||||
self.notifiers = notifiers
|
||||
|
||||
def find_applications(self) -> List[Application]:
|
||||
"""Get all application directories and their owners."""
|
||||
applications: List[Application] = []
|
||||
source_dirs = itertools.chain(*(root.iterdir() for root in self.roots))
|
||||
|
||||
for app_dir in source_dirs:
|
||||
if "lost+found" in str(app_dir):
|
||||
continue
|
||||
if app_dir.is_dir():
|
||||
try:
|
||||
stat_info = app_dir.stat()
|
||||
owner = pwd.getpwuid(stat_info.st_uid).pw_name
|
||||
applications.append(Application(path=app_dir, owner=owner))
|
||||
except (KeyError, OSError) as e:
|
||||
logger.warning(f"Could not get owner for {app_dir}: {e}")
|
||||
|
||||
return applications
|
||||
|
||||
def find_backup_script(self, app_dir: str) -> Optional[str]:
|
||||
"""Find backup script in user's home directory"""
|
||||
possible_scripts = [
|
||||
os.path.join(app_dir, "backup.sh"),
|
||||
os.path.join(app_dir, "backup"),
|
||||
]
|
||||
|
||||
for script_path in possible_scripts:
|
||||
if os.path.exists(script_path):
|
||||
# Check if file is executable
|
||||
if os.access(script_path, os.X_OK):
|
||||
return script_path
|
||||
else:
|
||||
logger.warning(
|
||||
f"Backup script {script_path} exists but is not executable"
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
def run_app_backup(self, script_path: str, app_dir: str, username: str) -> bool:
|
||||
"""Run backup script as the specified user"""
|
||||
try:
|
||||
logger.info(f"Running backup script {script_path} (user {username})")
|
||||
|
||||
# Use su to run the script as the user
|
||||
cmd = ["su", "--login", username, "--command", script_path]
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
cwd=app_dir,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=3600, # 1 hour timeout
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info(f"Backup script for {username} completed successfully")
|
||||
self.successful_backups.append(username)
|
||||
return True
|
||||
else:
|
||||
error_msg = f"Backup script {script_path} failed with return code {result.returncode}"
|
||||
if result.stderr:
|
||||
error_msg += f": {result.stderr}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"App {username}: {error_msg}")
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
error_msg = f"Backup script {script_path} timed out"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"App {username}: {error_msg}")
|
||||
return False
|
||||
except Exception as e:
|
||||
error_msg = f"Failed to run backup script {script_path}: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"App {username}: {error_msg}")
|
||||
return False
|
||||
|
||||
def get_backup_directories(self) -> List[str]:
|
||||
"""Collect backup targets according to backup-targets rules"""
|
||||
backup_dirs: List[str] = []
|
||||
applications = self.find_applications()
|
||||
|
||||
def parse_targets_file(targets_file: Path) -> List[str]:
|
||||
"""Parse backup-targets file, skipping comments and empty lines."""
|
||||
targets: List[str] = []
|
||||
try:
|
||||
for raw_line in targets_file.read_text(encoding="utf-8").splitlines():
|
||||
line = raw_line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
targets.append(line)
|
||||
except OSError as e:
|
||||
warning_msg = f"Could not read backup targets file {targets_file}: {e}"
|
||||
logger.warning(warning_msg)
|
||||
self.warnings.append(warning_msg)
|
||||
return targets
|
||||
|
||||
for app in applications:
|
||||
app_dir = app.path
|
||||
targets_file = app_dir / BACKUP_TARGETS_FILE
|
||||
resolved_targets: List[Path] = []
|
||||
|
||||
if targets_file.exists():
|
||||
# Read custom targets defined by the application.
|
||||
for target_line in parse_targets_file(targets_file):
|
||||
target_path = Path(target_line)
|
||||
if not target_path.is_absolute():
|
||||
target_path = (app_dir / target_path).resolve()
|
||||
else:
|
||||
target_path = target_path.resolve()
|
||||
if target_path.exists():
|
||||
resolved_targets.append(target_path)
|
||||
else:
|
||||
warning_msg = (
|
||||
f"Backup target does not exist for {app_dir}: {target_path}"
|
||||
)
|
||||
logger.warning(warning_msg)
|
||||
self.warnings.append(warning_msg)
|
||||
else:
|
||||
# Fallback to default backups directory when no list is provided.
|
||||
default_target = (app_dir / BACKUP_DEFAULT_DIR).resolve()
|
||||
if default_target.exists():
|
||||
resolved_targets.append(default_target)
|
||||
else:
|
||||
warning_msg = f"Default backup path does not exist for {app_dir}: {default_target}"
|
||||
logger.warning(warning_msg)
|
||||
self.warnings.append(warning_msg)
|
||||
|
||||
for target in resolved_targets:
|
||||
target_str = str(target)
|
||||
if target_str not in backup_dirs:
|
||||
backup_dirs.append(target_str)
|
||||
|
||||
return backup_dirs
|
||||
|
||||
def send_notification(self, success: bool) -> None:
|
||||
"""Send notification to Notifiers"""
|
||||
|
||||
if success and not self.errors:
|
||||
message = f"<b>{self.config.host_name}</b>: бекап успешно завершен!"
|
||||
if self.successful_backups:
|
||||
message += f"\n\nУспешные бекапы: {', '.join(self.successful_backups)}"
|
||||
else:
|
||||
message = f"<b>{self.config.host_name}</b>: бекап завершен с ошибками!"
|
||||
|
||||
if self.successful_backups:
|
||||
message += (
|
||||
f"\n\n✅ Успешные бекапы: {', '.join(self.successful_backups)}"
|
||||
)
|
||||
|
||||
if self.warnings:
|
||||
message += f"\n\n⚠️ Предупреждения:\n" + "\n".join(self.warnings)
|
||||
|
||||
if self.errors:
|
||||
message += f"\n\n❌ Ошибки:\n" + "\n".join(self.errors)
|
||||
|
||||
for notificator in self.notifiers:
|
||||
try:
|
||||
notificator.send(message)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send notification: {str(e)}")
|
||||
|
||||
def run_backup_process(self) -> bool:
|
||||
"""Main backup process"""
|
||||
logger.info("Starting backup process")
|
||||
|
||||
# Get all home directories
|
||||
applications = self.find_applications()
|
||||
logger.info(f"Found {len(applications)} application directories")
|
||||
|
||||
# Process each user's backup
|
||||
for app in applications:
|
||||
app_dir = str(app.path)
|
||||
username = app.owner
|
||||
logger.info(f"Processing backup for app: {app_dir} (user {username})")
|
||||
|
||||
# Find backup script
|
||||
backup_script = self.find_backup_script(app_dir)
|
||||
|
||||
if backup_script is None:
|
||||
warning_msg = (
|
||||
f"No backup script found for app: {app_dir} (user {username})"
|
||||
)
|
||||
logger.warning(warning_msg)
|
||||
self.warnings.append(warning_msg)
|
||||
continue
|
||||
|
||||
self.run_app_backup(backup_script, app_dir, username)
|
||||
|
||||
# Get backup directories
|
||||
backup_dirs = self.get_backup_directories()
|
||||
logger.info(f"Found backup directories: {backup_dirs}")
|
||||
|
||||
overall_success = True
|
||||
|
||||
for storage in self.storages:
|
||||
backup_result = storage.backup(backup_dirs)
|
||||
if not backup_result:
|
||||
self.errors.append("Restic backup failed")
|
||||
|
||||
# Determine overall success
|
||||
overall_success = overall_success and backup_result
|
||||
|
||||
# Send notification
|
||||
self.send_notification(overall_success)
|
||||
|
||||
logger.info("Backup process completed")
|
||||
|
||||
if self.errors:
|
||||
logger.error(f"Backup completed with {len(self.errors)} errors")
|
||||
return False
|
||||
elif self.warnings:
|
||||
logger.warning(f"Backup completed with {len(self.warnings)} warnings")
|
||||
return True
|
||||
else:
|
||||
logger.info("Backup completed successfully")
|
||||
return True
|
||||
|
||||
|
||||
def initialize(config_path: Path) -> BackupManager:
|
||||
try:
|
||||
with config_path.open("rb") as config_file:
|
||||
raw_config = tomllib.load(config_file)
|
||||
except OSError as e:
|
||||
logger.error(f"Failed to read config file {config_path}: {e}")
|
||||
raise
|
||||
|
||||
host_name = str(raw_config.get("host_name", "unknown"))
|
||||
|
||||
roots_raw = raw_config.get("roots") or []
|
||||
if not isinstance(roots_raw, list) or not roots_raw:
|
||||
raise ValueError("roots must be a non-empty list of paths in config.toml")
|
||||
roots = [Path(root) for root in roots_raw]
|
||||
|
||||
storage_raw = raw_config.get("storage") or {}
|
||||
storages: List[Storage] = []
|
||||
for name, params in storage_raw.items():
|
||||
if not isinstance(params, dict):
|
||||
raise ValueError(f"Storage config for {name} must be a table")
|
||||
storage_type = params.get("type", "")
|
||||
if storage_type == ResticStorage.TYPE_NAME:
|
||||
storages.append(ResticStorage(name, params))
|
||||
if not storages:
|
||||
raise ValueError("At least one storage backend must be configured")
|
||||
|
||||
notifications_raw = raw_config.get("notifier") or {}
|
||||
notifiers: List[Notifier] = []
|
||||
for name, params in notifications_raw.items():
|
||||
if not isinstance(params, dict):
|
||||
raise ValueError(f"Notificator config for {name} must be a table")
|
||||
notifier_type = params.get("type", "")
|
||||
if notifier_type == TelegramNotifier.TYPE_NAME:
|
||||
notifiers.append(TelegramNotifier(name, params))
|
||||
if not notifiers:
|
||||
raise ValueError("At least one notification backend must be configured")
|
||||
|
||||
config = Config(host_name=host_name, roots=roots)
|
||||
|
||||
return BackupManager(
|
||||
config=config, roots=roots, storages=storages, notifiers=notifiers
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
backup_manager = initialize(CONFIG_PATH)
|
||||
success = backup_manager.run_backup_process()
|
||||
if not success:
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Backup process interrupted by user")
|
||||
sys.exit(130)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in backup process: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,326 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Backup script for all applications
|
||||
Automatically discovers and runs backup scripts for all users,
|
||||
then creates restic backups and sends notifications.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import logging
|
||||
import pwd
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple, Optional
|
||||
import requests
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.StreamHandler(sys.stdout),
|
||||
logging.FileHandler("/var/log/backup-all.log"),
|
||||
],
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Configuration from Ansible template variables
|
||||
RESTIC_REPOSITORY = "{{ restic_repository }}"
|
||||
RESTIC_PASSWORD = "{{ restic_password }}"
|
||||
AWS_ACCESS_KEY_ID = "{{ restic_s3_access_key }}"
|
||||
AWS_SECRET_ACCESS_KEY = "{{ restic_s3_access_secret }}"
|
||||
AWS_DEFAULT_REGION = "{{ restic_s3_region }}"
|
||||
TELEGRAM_BOT_TOKEN = "{{ notifications_tg_bot_token }}"
|
||||
TELEGRAM_CHAT_ID = "{{ notifications_tg_chat_id }}"
|
||||
NOTIFICATIONS_NAME = "{{ notifications_name }}"
|
||||
|
||||
|
||||
class BackupManager:
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
self.warnings = []
|
||||
self.successful_backups = []
|
||||
|
||||
def get_home_directories(self) -> List[Tuple[str, str]]:
|
||||
"""Get all home directories and their owners"""
|
||||
home_dirs = []
|
||||
home_path = Path("/home")
|
||||
|
||||
if not home_path.exists():
|
||||
logger.error("/home directory does not exist")
|
||||
return home_dirs
|
||||
|
||||
for user_dir in home_path.iterdir():
|
||||
if user_dir.is_dir():
|
||||
try:
|
||||
# Get the owner of the directory
|
||||
stat_info = user_dir.stat()
|
||||
owner = pwd.getpwuid(stat_info.st_uid).pw_name
|
||||
home_dirs.append((str(user_dir), owner))
|
||||
except (KeyError, OSError) as e:
|
||||
logger.warning(f"Could not get owner for {user_dir}: {e}")
|
||||
|
||||
return home_dirs
|
||||
|
||||
def find_backup_script(self, home_dir: str) -> Optional[str]:
|
||||
"""Find backup script in user's home directory"""
|
||||
possible_scripts = [
|
||||
os.path.join(home_dir, "backup.sh"),
|
||||
os.path.join(home_dir, "backup"),
|
||||
]
|
||||
|
||||
for script_path in possible_scripts:
|
||||
if os.path.exists(script_path):
|
||||
# Check if file is executable
|
||||
if os.access(script_path, os.X_OK):
|
||||
return script_path
|
||||
else:
|
||||
logger.warning(
|
||||
f"Backup script {script_path} exists but is not executable"
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
def run_user_backup(self, script_path: str, username: str) -> bool:
|
||||
"""Run backup script as the specified user"""
|
||||
try:
|
||||
logger.info(f"Running backup script {script_path} as user {username}")
|
||||
|
||||
# Use su to run the script as the user
|
||||
cmd = ["su", "--login", username, "--command", script_path]
|
||||
|
||||
result = subprocess.run(
|
||||
cmd, capture_output=True, text=True, timeout=3600 # 1 hour timeout
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info(f"Backup script for {username} completed successfully")
|
||||
self.successful_backups.append(username)
|
||||
return True
|
||||
else:
|
||||
error_msg = f"Backup script for {username} failed with return code {result.returncode}"
|
||||
if result.stderr:
|
||||
error_msg += f": {result.stderr}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"User {username}: {error_msg}")
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
error_msg = f"Backup script for {username} timed out"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"User {username}: {error_msg}")
|
||||
return False
|
||||
except Exception as e:
|
||||
error_msg = f"Failed to run backup script for {username}: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"User {username}: {error_msg}")
|
||||
return False
|
||||
|
||||
def get_backup_directories(self) -> List[str]:
|
||||
"""Get all backup directories that exist"""
|
||||
backup_dirs = []
|
||||
home_dirs = self.get_home_directories()
|
||||
|
||||
for home_dir, _ in home_dirs:
|
||||
backup_path = os.path.join(home_dir, "backups")
|
||||
if os.path.exists(backup_path) and os.path.isdir(backup_path):
|
||||
backup_dirs.append(backup_path)
|
||||
|
||||
return backup_dirs
|
||||
|
||||
def run_restic_backup(self, backup_dirs: List[str]) -> bool:
|
||||
"""Run restic backup for all backup directories"""
|
||||
if not backup_dirs:
|
||||
logger.warning("No backup directories found")
|
||||
return True
|
||||
|
||||
try:
|
||||
logger.info("Starting restic backup")
|
||||
|
||||
# Set environment variables for restic
|
||||
env = os.environ.copy()
|
||||
env.update(
|
||||
{
|
||||
"RESTIC_REPOSITORY": RESTIC_REPOSITORY,
|
||||
"RESTIC_PASSWORD": RESTIC_PASSWORD,
|
||||
"AWS_ACCESS_KEY_ID": AWS_ACCESS_KEY_ID,
|
||||
"AWS_SECRET_ACCESS_KEY": AWS_SECRET_ACCESS_KEY,
|
||||
"AWS_DEFAULT_REGION": AWS_DEFAULT_REGION,
|
||||
}
|
||||
)
|
||||
|
||||
# Run backup
|
||||
backup_cmd = ["restic", "backup", "--verbose"] + backup_dirs
|
||||
result = subprocess.run(backup_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
error_msg = f"Restic backup failed: {result.stderr}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"Restic backup: {error_msg}")
|
||||
return False
|
||||
|
||||
logger.info("Restic backup completed successfully")
|
||||
|
||||
# Run check
|
||||
check_cmd = ["restic", "check"]
|
||||
result = subprocess.run(check_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
error_msg = f"Restic check failed: {result.stderr}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"Restic check: {error_msg}")
|
||||
return False
|
||||
|
||||
logger.info("Restic check completed successfully")
|
||||
|
||||
# Run forget and prune
|
||||
forget_cmd = [
|
||||
"restic",
|
||||
"forget",
|
||||
"--compact",
|
||||
"--prune",
|
||||
"--keep-daily",
|
||||
"90",
|
||||
"--keep-monthly",
|
||||
"36",
|
||||
]
|
||||
result = subprocess.run(forget_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
error_msg = f"Restic forget/prune failed: {result.stderr}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"Restic forget/prune: {error_msg}")
|
||||
return False
|
||||
|
||||
logger.info("Restic forget/prune completed successfully")
|
||||
|
||||
# Final check
|
||||
result = subprocess.run(check_cmd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
error_msg = f"Final restic check failed: {result.stderr}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"Final restic check: {error_msg}")
|
||||
return False
|
||||
|
||||
logger.info("Final restic check completed successfully")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Restic backup process failed: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
self.errors.append(f"Restic: {error_msg}")
|
||||
return False
|
||||
|
||||
def send_telegram_notification(self, success: bool) -> None:
|
||||
"""Send notification to Telegram"""
|
||||
try:
|
||||
if success and not self.errors:
|
||||
message = f"<b>{NOTIFICATIONS_NAME}</b>: бекап успешно завершен!"
|
||||
if self.successful_backups:
|
||||
message += (
|
||||
f"\n\nУспешные бекапы: {', '.join(self.successful_backups)}"
|
||||
)
|
||||
else:
|
||||
message = f"<b>{NOTIFICATIONS_NAME}</b>: бекап завершен с ошибками!"
|
||||
|
||||
if self.successful_backups:
|
||||
message += (
|
||||
f"\n\n✅ Успешные бекапы: {', '.join(self.successful_backups)}"
|
||||
)
|
||||
|
||||
if self.warnings:
|
||||
message += f"\n\n⚠️ Предупреждения:\n" + "\n".join(self.warnings)
|
||||
|
||||
if self.errors:
|
||||
message += f"\n\n❌ Ошибки:\n" + "\n".join(self.errors)
|
||||
|
||||
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
|
||||
data = {"chat_id": TELEGRAM_CHAT_ID, "parse_mode": "HTML", "text": message}
|
||||
|
||||
response = requests.post(url, data=data, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
logger.info("Telegram notification sent successfully")
|
||||
else:
|
||||
logger.error(
|
||||
f"Failed to send Telegram notification: {response.status_code} - {response.text}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send Telegram notification: {str(e)}")
|
||||
|
||||
def run_backup_process(self) -> bool:
|
||||
"""Main backup process"""
|
||||
logger.info("Starting backup process")
|
||||
|
||||
# Get all home directories
|
||||
home_dirs = self.get_home_directories()
|
||||
logger.info(f"Found {len(home_dirs)} home directories")
|
||||
|
||||
# Process each user's backup
|
||||
for home_dir, username in home_dirs:
|
||||
logger.info(f"Processing backup for user: {username} ({home_dir})")
|
||||
|
||||
# Find backup script
|
||||
backup_script = self.find_backup_script(home_dir)
|
||||
|
||||
if backup_script is None:
|
||||
warning_msg = (
|
||||
f"No backup script found for user {username} in {home_dir}"
|
||||
)
|
||||
logger.warning(warning_msg)
|
||||
self.warnings.append(warning_msg)
|
||||
continue
|
||||
|
||||
# Run backup script
|
||||
self.run_user_backup(backup_script, username)
|
||||
|
||||
# Get backup directories
|
||||
backup_dirs = self.get_backup_directories()
|
||||
logger.info(f"Found backup directories: {backup_dirs}")
|
||||
|
||||
# Run restic backup
|
||||
restic_success = self.run_restic_backup(backup_dirs)
|
||||
|
||||
# Determine overall success
|
||||
overall_success = restic_success and len(self.errors) == 0
|
||||
|
||||
# Send notification
|
||||
self.send_telegram_notification(overall_success)
|
||||
|
||||
logger.info("Backup process completed")
|
||||
|
||||
if self.errors:
|
||||
logger.error(f"Backup completed with {len(self.errors)} errors")
|
||||
return False
|
||||
elif self.warnings:
|
||||
logger.warning(f"Backup completed with {len(self.warnings)} warnings")
|
||||
return True
|
||||
else:
|
||||
logger.info("Backup completed successfully")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point"""
|
||||
try:
|
||||
backup_manager = BackupManager()
|
||||
success = backup_manager.run_backup_process()
|
||||
|
||||
if success:
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Backup process interrupted by user")
|
||||
sys.exit(130)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in backup process: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
18
files/backups/config.template.toml
Normal file
18
files/backups/config.template.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
host_name = "{{ notifications_name }}"
|
||||
|
||||
roots = [
|
||||
"{{ application_dir }}"
|
||||
]
|
||||
|
||||
[storage.yandex_cloud_s3]
|
||||
type = "restic"
|
||||
restic_repository = "{{ restic_repository }}"
|
||||
restic_password = "{{ restic_password }}"
|
||||
aws_access_key_id = "{{ restic_s3_access_key }}"
|
||||
aws_secret_access_key = "{{ restic_s3_access_secret }}"
|
||||
aws_default_region = "{{ restic_s3_region }}"
|
||||
|
||||
[notifier.server_notifications_channel]
|
||||
type = "telegram"
|
||||
telegram_bot_token = "{{ notifications_tg_bot_token }}"
|
||||
telegram_chat_id = "{{ notifications_tg_chat_id }}"
|
||||
@@ -89,6 +89,14 @@ wanderer.vakhrushev.me {
|
||||
}
|
||||
|
||||
memos.vakhrushev.me {
|
||||
tls anwinged@ya.ru
|
||||
|
||||
reverse_proxy {
|
||||
to memos_app:5230
|
||||
}
|
||||
}
|
||||
|
||||
wanderbase.vakhrushev.me {
|
||||
tls anwinged@ya.ru
|
||||
|
||||
forward_auth authelia_app:9091 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
services:
|
||||
|
||||
dozzle_app:
|
||||
image: amir20/dozzle:v8.14.5
|
||||
image: amir20/dozzle:v8.14.11
|
||||
container_name: dozzle_app
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
@@ -1,11 +1,10 @@
|
||||
services:
|
||||
|
||||
gitea_app:
|
||||
image: gitea/gitea:1.24.6
|
||||
image: gitea/gitea:1.25.3
|
||||
restart: unless-stopped
|
||||
container_name: gitea_app
|
||||
ports:
|
||||
- "127.0.0.1:{{ gitea_port }}:3000"
|
||||
- "2222:22"
|
||||
volumes:
|
||||
- {{ data_dir }}:/data
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
services:
|
||||
|
||||
gramps_app: &gramps_app
|
||||
image: ghcr.io/gramps-project/grampsweb:25.9.0
|
||||
image: ghcr.io/gramps-project/grampsweb:25.11.2
|
||||
container_name: gramps_app
|
||||
depends_on:
|
||||
- gramps_redis
|
||||
@@ -15,10 +15,10 @@ services:
|
||||
- "{{ (data_dir, 'gramps_db') | path_join }}:/root/.gramps/grampsdb" # persist Gramps database
|
||||
- "{{ (data_dir, 'gramps_users') | path_join }}:/app/users" # persist user database
|
||||
- "{{ (data_dir, 'gramps_index') | path_join }}:/app/indexdir" # persist search index
|
||||
- "{{ (data_dir, 'gramps_thumb_cache') | path_join }}:/app/thumbnail_cache" # persist thumbnails
|
||||
- "{{ (data_dir, 'gramps_cache') | path_join }}:/app/cache" # persist export and report caches
|
||||
- "{{ (data_dir, 'gramps_secret') | path_join }}:/app/secret" # persist flask secret
|
||||
- "{{ (data_dir, 'gramps_media') | path_join }}:/app/media" # persist media files
|
||||
- "{{ (cache_dir, 'gramps_thumb_cache') | path_join }}:/app/thumbnail_cache" # persist thumbnails
|
||||
- "{{ (cache_dir, 'gramps_cache') | path_join }}:/app/cache" # persist export and report caches
|
||||
- "{{ media_dir }}:/app/media" # persist media files
|
||||
environment:
|
||||
GRAMPSWEB_TREE: "Gramps" # will create a new tree if not exists
|
||||
GRAMPSWEB_SECRET_KEY: "{{ gramps_secret_key }}"
|
||||
@@ -37,12 +37,8 @@ services:
|
||||
GRAMPSWEB_EMAIL_USE_TLS: "false"
|
||||
GRAMPSWEB_DEFAULT_FROM_EMAIL: "gramps@vakhrushev.me"
|
||||
|
||||
# media storage at s3
|
||||
GRAMPSWEB_MEDIA_BASE_DIR: "s3://av-gramps-media-storage"
|
||||
AWS_ENDPOINT_URL: "{{ gramps_s3_endpoint }}"
|
||||
AWS_ACCESS_KEY_ID: "{{ gramps_s3_access_key_id }}"
|
||||
AWS_SECRET_ACCESS_KEY: "{{ gramps_s3_secret_access_key }}"
|
||||
AWS_DEFAULT_REGION: "{{ gramps_s3_region }}"
|
||||
# media storage
|
||||
GRAMPSWEB_MEDIA_BASE_DIR: "/app/media"
|
||||
|
||||
gramps_celery:
|
||||
<<: *gramps_app # YAML merge key copying the entire grampsweb service config
|
||||
@@ -53,10 +49,10 @@ services:
|
||||
ports: []
|
||||
networks:
|
||||
- "gramps_network"
|
||||
command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2
|
||||
command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=1
|
||||
|
||||
gramps_redis:
|
||||
image: valkey/valkey:8.1.1-alpine
|
||||
image: valkey/valkey:9.0-alpine
|
||||
container_name: gramps_redis
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
@@ -23,10 +23,3 @@ models:
|
||||
undo:
|
||||
type: sqlite
|
||||
path: "{{ (data_dir, 'gramps_db/59a0f3d6-1c3d-4410-8c1d-1c9c6689659f/undo.db') | path_join }}"
|
||||
archive:
|
||||
includes:
|
||||
- "{{ data_dir }}"
|
||||
excludes:
|
||||
- "{{ (data_dir, 'gramps_cache') | path_join }}"
|
||||
- "{{ (data_dir, 'gramps_thumb_cache') | path_join }}"
|
||||
- "{{ (data_dir, 'gramps_tmp') | path_join }}"
|
||||
65
files/gramps/gramps_rename.py
Executable file
65
files/gramps/gramps_rename.py
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3.12
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Rename Gramps document files by appending extensions from a list."
|
||||
)
|
||||
parser.add_argument("directory", type=Path, help="Directory containing hashed files")
|
||||
parser.add_argument("names_file", type=Path, help="Text file with target names")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def read_names(path: Path) -> list[str]:
|
||||
if not path.is_file():
|
||||
raise FileNotFoundError(f"Names file not found: {path}")
|
||||
|
||||
names = []
|
||||
for line in path.read_text(encoding="utf-8").splitlines():
|
||||
name = line.strip()
|
||||
if name:
|
||||
names.append(name)
|
||||
return names
|
||||
|
||||
|
||||
def rename_files(directory: Path, names: list[str]) -> None:
|
||||
if not directory.is_dir():
|
||||
raise NotADirectoryError(f"Directory not found: {directory}")
|
||||
|
||||
for name in names:
|
||||
hash_part, dot, _ = name.partition(".")
|
||||
if not dot:
|
||||
print(f"Skipping invalid entry (missing extension): {name}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
source = directory / hash_part
|
||||
target = directory / name
|
||||
|
||||
if target.exists():
|
||||
print(f"Target already exists, skipping: {target}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if not source.exists():
|
||||
print(f"Source not found, skipping: {source}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
source.rename(target)
|
||||
print(f"Renamed {source.name} -> {target.name}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
try:
|
||||
names = read_names(args.names_file)
|
||||
rename_files(args.directory, names)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print(str(exc), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,14 +1,13 @@
|
||||
services:
|
||||
|
||||
homepage_app:
|
||||
image: "{{ registry_homepage_web_image }}"
|
||||
# noinspection ComposeUnknownValues
|
||||
image: "{{ registry_homepage_nginx_image }}"
|
||||
container_name: homepage_app
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:{{ homepage_port }}:80"
|
||||
networks:
|
||||
- "web_proxy_network"
|
||||
|
||||
networks:
|
||||
web_proxy_network:
|
||||
external: true
|
||||
|
||||
10
files/memos/backup.sh.j2
Normal file
10
files/memos/backup.sh.j2
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
echo "{{ app_name }}: backup data with gobackups"
|
||||
|
||||
(cd "{{ base_dir }}" && gobackup perform --config "{{ gobackup_config }}")
|
||||
|
||||
echo "{{ app_name }}: done."
|
||||
23
files/memos/docker-compose.template.yml
Normal file
23
files/memos/docker-compose.template.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
# See versions: https://github.com/gramps-project/gramps-web/pkgs/container/grampsweb
|
||||
|
||||
services:
|
||||
|
||||
memos_app:
|
||||
image: neosmemo/memos:0.25.3
|
||||
container_name: memos_app
|
||||
restart: unless-stopped
|
||||
user: "{{ user_create_result.uid }}:{{ user_create_result.group }}"
|
||||
networks:
|
||||
- "web_proxy_network"
|
||||
volumes:
|
||||
- "{{ data_dir }}:/var/opt/memos"
|
||||
environment:
|
||||
- MEMOS_MODE=prod
|
||||
- MEMOS_PORT=5230
|
||||
- MEMOS_STORAGE_TYPE=local
|
||||
- MEMOS_STORAGE_PATH=assets/{uuid}
|
||||
- MEMOS_MAX_FILE_SIZE=52428800
|
||||
|
||||
networks:
|
||||
web_proxy_network:
|
||||
external: true
|
||||
16
files/memos/gobackup.yml.j2
Normal file
16
files/memos/gobackup.yml.j2
Normal file
@@ -0,0 +1,16 @@
|
||||
# https://gobackup.github.io/configuration
|
||||
|
||||
models:
|
||||
|
||||
memos:
|
||||
compress_with:
|
||||
type: 'tgz'
|
||||
storages:
|
||||
local:
|
||||
type: 'local'
|
||||
path: '{{ backups_dir }}'
|
||||
keep: 3
|
||||
databases:
|
||||
users:
|
||||
type: sqlite
|
||||
path: "{{ (data_dir, 'memos_prod.db') | path_join }}"
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
services:
|
||||
|
||||
netdata:
|
||||
image: netdata/netdata:v2.7.1
|
||||
image: netdata/netdata:v2.8.4
|
||||
container_name: netdata
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
@@ -17,12 +16,16 @@ services:
|
||||
- "{{ config_dir }}:/etc/netdata"
|
||||
- "{{ (data_dir, 'lib') | path_join }}:/var/lib/netdata"
|
||||
- "{{ (data_dir, 'cache') | path_join }}:/var/cache/netdata"
|
||||
|
||||
# Netdata system volumes
|
||||
- "/:/host/root:ro,rslave"
|
||||
|
||||
- "/etc/group:/host/etc/group:ro"
|
||||
- "/etc/hostname:/host/etc/hostname:ro"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
- "/etc/os-release:/host/etc/os-release:ro"
|
||||
- "/etc/passwd:/host/etc/passwd:ro"
|
||||
|
||||
- "/proc:/host/proc:ro"
|
||||
- "/run/dbus:/run/dbus:ro"
|
||||
- "/sys:/host/sys:ro"
|
||||
@@ -1,3 +1,3 @@
|
||||
jobs:
|
||||
- name: fail2ban
|
||||
update_every: 15 # Collect Fail2Ban jails statistics every 15 seconds
|
||||
update_every: 60 # Collect Fail2Ban jails statistics every N seconds
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
update_every: 15
|
||||
update_every: 60
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# cpu cores = 2
|
||||
# libuv worker threads = 16
|
||||
# profile = standalone
|
||||
hostname = {{ host_name }}
|
||||
# hostname = rivendell-v2
|
||||
# glibc malloc arena max for plugins = 1
|
||||
# glibc malloc arena max for netdata = 1
|
||||
# crash reports = all
|
||||
@@ -30,12 +30,15 @@
|
||||
# has unstable connection = no
|
||||
|
||||
[db]
|
||||
#| >>> [db].update every <<<
|
||||
#| datatype: duration (seconds), default value: 1s
|
||||
update every = 10s
|
||||
|
||||
# enable replication = yes
|
||||
# replication period = 1d
|
||||
# replication step = 1h
|
||||
# replication threads = 1
|
||||
# replication prefetch = 10
|
||||
# update every = 1s
|
||||
# db = dbengine
|
||||
# memory deduplication (ksm) = auto
|
||||
# cleanup orphan hosts after = 1h
|
||||
@@ -47,7 +50,7 @@
|
||||
# dbengine extent cache size = off
|
||||
# dbengine enable journal integrity check = no
|
||||
# dbengine use all ram for caches = no
|
||||
# dbengine out of memory protection = 391.99MiB
|
||||
# dbengine out of memory protection = 391.49MiB
|
||||
# dbengine use direct io = yes
|
||||
# dbengine journal v2 unmount time = 2m
|
||||
# dbengine pages per extent = 109
|
||||
@@ -96,9 +99,6 @@
|
||||
# PYTHONPATH =
|
||||
# TZ = :/etc/localtime
|
||||
|
||||
[host labels]
|
||||
# name = value
|
||||
|
||||
[cloud]
|
||||
# conversation log = no
|
||||
# scope = full
|
||||
@@ -107,15 +107,15 @@
|
||||
|
||||
[ml]
|
||||
# enabled = auto
|
||||
# maximum num samples to train = 21600
|
||||
# minimum num samples to train = 900
|
||||
# training window = 6h
|
||||
# min training window = 15m
|
||||
# max training vectors = 1440
|
||||
# max samples to smooth = 3
|
||||
# train every = 3h
|
||||
# number of models per dimension = 18
|
||||
# delete models older than = 7d
|
||||
# num samples to diff = 1
|
||||
# num samples to smooth = 3
|
||||
# num samples to lag = 5
|
||||
# random sampling ratio = 0.20000
|
||||
# maximum number of k-means iterations = 1000
|
||||
# dimension anomaly score threshold = 0.99000
|
||||
# host anomaly rate threshold = 1.00000
|
||||
@@ -181,7 +181,7 @@
|
||||
# gzip compression level = 3
|
||||
# ssl skip certificate verification = no
|
||||
# web server threads = 6
|
||||
# web server max sockets = 262144
|
||||
# web server max sockets = 131072
|
||||
|
||||
[registry]
|
||||
# enabled = no
|
||||
@@ -191,7 +191,7 @@
|
||||
# registry expire idle persons = 1y
|
||||
# registry domain =
|
||||
# registry to announce = https://registry.my-netdata.io
|
||||
# registry hostname = 7171b7f9fc69
|
||||
# registry hostname = rivendell-v2
|
||||
# verify browser cookies support = yes
|
||||
# enable cookies SameSite and Secure = yes
|
||||
# max URL length = 1024
|
||||
@@ -202,9 +202,29 @@
|
||||
|
||||
[pulse]
|
||||
# extended = no
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
|
||||
[plugins]
|
||||
#| >>> [plugins].perf <<<
|
||||
#| datatype: yes or no, default value: yes
|
||||
perf = no
|
||||
|
||||
#| >>> [plugins].python.d <<<
|
||||
#| datatype: yes or no, default value: yes
|
||||
python.d = no
|
||||
|
||||
#| >>> [plugins].charts.d <<<
|
||||
#| datatype: yes or no, default value: yes
|
||||
charts.d = no
|
||||
|
||||
#| >>> [plugins].otel <<<
|
||||
#| datatype: yes or no, default value: yes
|
||||
otel = no
|
||||
|
||||
#| >>> [plugins].statsd <<<
|
||||
#| datatype: yes or no, default value: yes
|
||||
statsd = no
|
||||
|
||||
# idlejitter = yes
|
||||
# netdata pulse = yes
|
||||
# profile = no
|
||||
@@ -213,23 +233,20 @@
|
||||
# proc = yes
|
||||
# cgroups = yes
|
||||
# timex = yes
|
||||
# statsd = yes
|
||||
# enable running new plugins = yes
|
||||
# check for new plugins every = 1m
|
||||
# slabinfo = no
|
||||
# freeipmi = no
|
||||
# python.d = yes
|
||||
# go.d = yes
|
||||
# apps = yes
|
||||
# systemd-journal = yes
|
||||
# network-viewer = yes
|
||||
# charts.d = yes
|
||||
# debugfs = yes
|
||||
# perf = yes
|
||||
# ioping = yes
|
||||
# network-viewer = yes
|
||||
# apps = yes
|
||||
# go.d = yes
|
||||
# systemd-units = yes
|
||||
# systemd-journal = yes
|
||||
|
||||
[statsd]
|
||||
# update every (flushInterval) = 1s
|
||||
# update every (flushInterval) = 10s
|
||||
# udp messages to process at once = 10
|
||||
# create private charts for metrics matching = *
|
||||
# max private charts hard limit = 1000
|
||||
@@ -247,10 +264,7 @@
|
||||
# gaps on histograms (deleteHistograms) = no
|
||||
# gaps on timers (deleteTimers) = no
|
||||
# gaps on dictionaries (deleteDictionaries) = no
|
||||
# statsd server max TCP sockets = 262144
|
||||
# listen backlog = 4096
|
||||
# default port = 8125
|
||||
# bind to = udp:localhost tcp:localhost
|
||||
# statsd server max TCP sockets = 131072
|
||||
|
||||
[plugin:idlejitter]
|
||||
# loop time = 20ms
|
||||
@@ -300,8 +314,14 @@
|
||||
# /sys/class/drm = yes
|
||||
|
||||
[plugin:cgroups]
|
||||
# update every = 1s
|
||||
# check for new cgroups every = 10s
|
||||
#| >>> [plugin:cgroups].update every <<<
|
||||
#| datatype: duration (seconds), default value: 10s
|
||||
update every = 20s
|
||||
|
||||
#| >>> [plugin:cgroups].check for new cgroups every <<<
|
||||
#| datatype: duration (seconds), default value: 10s
|
||||
check for new cgroups every = 20s
|
||||
|
||||
# use unified cgroups = auto
|
||||
# max cgroups to allow = 1000
|
||||
# max cgroups depth to monitor = 0
|
||||
@@ -314,8 +334,11 @@
|
||||
# cgroups to match as systemd services = !/system.slice/*/*.service /system.slice/*.service
|
||||
|
||||
[plugin:proc:diskspace]
|
||||
#| >>> [plugin:proc:diskspace].update every <<<
|
||||
#| datatype: duration (seconds), default value: 10s
|
||||
update every = 1m
|
||||
|
||||
# remove charts of unmounted disks = yes
|
||||
# update every = 1s
|
||||
# check for new mount points every = 15s
|
||||
# exclude space metrics on paths = /dev /dev/shm /proc/* /sys/* /var/run/user/* /run/lock /run/user/* /snap/* /var/lib/docker/* /var/lib/containers/storage/* /run/credentials/* /run/containerd/* /rpool /rpool/*
|
||||
# exclude space metrics on filesystems = *gvfs *gluster* *s3fs *ipfs *davfs2 *httpfs *sshfs *gdfs *moosefs fusectl autofs cgroup cgroup2 hugetlbfs devtmpfs fuse.lxcfs
|
||||
@@ -326,40 +349,28 @@
|
||||
[plugin:tc]
|
||||
# script to run to get tc values = /usr/libexec/netdata/plugins.d/tc-qos-helper.sh
|
||||
|
||||
[plugin:python.d]
|
||||
# update every = 1s
|
||||
# command options =
|
||||
|
||||
[plugin:go.d]
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
# command options =
|
||||
|
||||
[plugin:apps]
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
# command options =
|
||||
|
||||
[plugin:systemd-journal]
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
# command options =
|
||||
|
||||
[plugin:network-viewer]
|
||||
# update every = 1s
|
||||
# command options =
|
||||
|
||||
[plugin:charts.d]
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
# command options =
|
||||
|
||||
[plugin:debugfs]
|
||||
# update every = 1s
|
||||
# command options =
|
||||
|
||||
[plugin:perf]
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
# command options =
|
||||
|
||||
[plugin:ioping]
|
||||
# update every = 1s
|
||||
# update every = 10s
|
||||
# command options =
|
||||
|
||||
[plugin:proc:/proc/net/dev]
|
||||
@@ -635,7 +646,7 @@
|
||||
# preferred disk ids = *
|
||||
# exclude disks = loop* ram*
|
||||
# filename to monitor = /host/proc/diskstats
|
||||
# performance metrics for disks with major 252 = yes
|
||||
# performance metrics for disks with major 253 = yes
|
||||
|
||||
[plugin:proc:/proc/mdstat]
|
||||
# faulty devices = yes
|
||||
@@ -685,3 +696,7 @@
|
||||
|
||||
[plugin:proc:/sys/class/drm]
|
||||
# directory to monitor = /host/sys/class/drm
|
||||
|
||||
[plugin:systemd-units]
|
||||
# update every = 10s
|
||||
# command options =
|
||||
@@ -3,14 +3,12 @@ services:
|
||||
# See sample https://github.com/outline/outline/blob/main/.env.sample
|
||||
|
||||
outline_app:
|
||||
image: outlinewiki/outline:0.87.4
|
||||
image: outlinewiki/outline:1.1.0
|
||||
container_name: outline_app
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- outline_postgres
|
||||
- outline_redis
|
||||
ports:
|
||||
- "127.0.0.1:{{ outline_port }}:3000"
|
||||
networks:
|
||||
- "outline_network"
|
||||
- "web_proxy_network"
|
||||
@@ -20,7 +18,7 @@ services:
|
||||
FORCE_HTTPS: 'true'
|
||||
SECRET_KEY: '{{ outline_secret_key }}'
|
||||
UTILS_SECRET: '{{ outline_utils_secret }}'
|
||||
DATABASE_URL: 'postgres://{{ outline_postgres_user }}:{{ outline_postgres_password }}@outline_postgres:5432/{{ outline_postgres_database }}'
|
||||
DATABASE_URL: 'postgres://{{ outline_postgres_user }}:{{ outline_postgres_password }}@outline_postgres:5432/{{ outline_postgres_database }}' # yamllint disable-line rule:line-length
|
||||
PGSSLMODE: 'disable'
|
||||
REDIS_URL: 'redis://outline_redis:6379'
|
||||
|
||||
@@ -54,7 +52,7 @@ services:
|
||||
SMTP_SECURE: 'false'
|
||||
|
||||
outline_redis:
|
||||
image: valkey/valkey:8.1.1-alpine
|
||||
image: valkey/valkey:9.0-alpine
|
||||
container_name: outline_redis
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
@@ -64,16 +62,22 @@ services:
|
||||
outline_postgres:
|
||||
image: postgres:16.3-bookworm
|
||||
container_name: outline_postgres
|
||||
user: "{{ user_create_result.uid }}:{{ user_create_result.group }}"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- {{ postgres_data_dir }}:/var/lib/postgresql/data
|
||||
networks:
|
||||
- "outline_network"
|
||||
- "monitoring_network"
|
||||
- "/etc/passwd:/etc/passwd:ro"
|
||||
- "{{ postgres_data_dir }}:/var/lib/postgresql/data"
|
||||
environment:
|
||||
POSTGRES_USER: '{{ outline_postgres_user }}'
|
||||
POSTGRES_PASSWORD: '{{ outline_postgres_password }}'
|
||||
POSTGRES_DB: '{{ outline_postgres_database }}'
|
||||
networks:
|
||||
- "outline_network"
|
||||
- "monitoring_network"
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "--username={{ outline_postgres_user }}", "--dbname={{ outline_postgres_database }}"]
|
||||
interval: 10s
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
outline_network:
|
||||
@@ -1,9 +1,10 @@
|
||||
services:
|
||||
|
||||
transcriber_app:
|
||||
# noinspection ComposeUnknownValues
|
||||
image: "{{ registry_transcriber_image }}"
|
||||
container_name: transcriber_app
|
||||
user: '{{ user_create_result.uid }}:{{ user_create_result.group }}'
|
||||
user: "{{ user_create_result.uid }}:{{ user_create_result.group }}"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- "{{ config_file }}:/config/config.toml:ro"
|
||||
@@ -3,7 +3,7 @@
|
||||
services:
|
||||
|
||||
wakapi_app:
|
||||
image: ghcr.io/muety/wakapi:2.16.0
|
||||
image: ghcr.io/muety/wakapi:2.16.1
|
||||
container_name: wakapi_app
|
||||
restart: unless-stopped
|
||||
user: '{{ user_create_result.uid }}:{{ user_create_result.group }}'
|
||||
@@ -17,6 +17,11 @@ services:
|
||||
WAKAPI_ALLOW_SIGNUP: "false"
|
||||
WAKAPI_DISABLE_FRONTPAGE: "true"
|
||||
WAKAPI_COOKIE_MAX_AGE: 31536000
|
||||
# OIDC
|
||||
# WAKAPI_OIDC_PROVIDER_NAME: "authelia"
|
||||
# WAKAPI_OIDC_PROVIDER_CLIENT_ID: "{{ wakapi_oidc_client_id }}"
|
||||
# WAKAPI_OIDC_PROVIDER_CLIENT_SECRET: "{{ wakapi_oidc_client_secret }}"
|
||||
# WAKAPI_OIDC_PROVIDER_ENDPOINT: "https://auth.vakhrushev.me/.well-known/openid-configuration"
|
||||
# Mail
|
||||
WAKAPI_MAIL_SENDER: "Wakapi <wakapi@vakhrushev.me>"
|
||||
WAKAPI_MAIL_PROVIDER: "smtp"
|
||||
@@ -26,7 +31,6 @@ services:
|
||||
WAKAPI_MAIL_SMTP_PASS: "{{ postbox_pass }}"
|
||||
WAKAPI_MAIL_SMTP_TLS: "false"
|
||||
|
||||
|
||||
networks:
|
||||
web_proxy_network:
|
||||
external: true
|
||||
|
||||
11
lefthook.yml
11
lefthook.yml
@@ -1,6 +1,8 @@
|
||||
# Refer for explanation to following link:
|
||||
# https://lefthook.dev/configuration/
|
||||
|
||||
glob_matcher: doublestar
|
||||
|
||||
templates:
|
||||
av-hooks-dir: "/home/av/projects/private/git-hooks"
|
||||
|
||||
@@ -12,3 +14,12 @@ pre-commit:
|
||||
|
||||
- name: "check secret files"
|
||||
run: "python3 {av-hooks-dir}/pre-commit/check-secrets-encrypted-with-ansible-vault.py"
|
||||
|
||||
- name: "format python"
|
||||
glob: "**/*.py"
|
||||
run: "black --quiet {staged_files}"
|
||||
stage_fixed: true
|
||||
|
||||
- name: "mypy"
|
||||
glob: "**/*.py"
|
||||
run: "mypy {staged_files}"
|
||||
|
||||
48
playbook-all-applications.yml
Normal file
48
playbook-all-applications.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
- name: 'Configure netdata'
|
||||
ansible.builtin.import_playbook: playbook-netdata.yml
|
||||
|
||||
#
|
||||
|
||||
- name: 'Configure dozzle'
|
||||
ansible.builtin.import_playbook: playbook-dozzle.yml
|
||||
|
||||
- name: 'Configure gitea'
|
||||
ansible.builtin.import_playbook: playbook-gitea.yml
|
||||
|
||||
- name: 'Configure gramps'
|
||||
ansible.builtin.import_playbook: playbook-gramps.yml
|
||||
|
||||
- name: 'Configure memos'
|
||||
ansible.builtin.import_playbook: playbook-memos.yml
|
||||
|
||||
- name: 'Configure miniflux'
|
||||
ansible.builtin.import_playbook: playbook-miniflux.yml
|
||||
|
||||
- name: 'Configure outline'
|
||||
ansible.builtin.import_playbook: playbook-outline.yml
|
||||
|
||||
- name: 'Configure rssbridge'
|
||||
ansible.builtin.import_playbook: playbook-rssbridge.yml
|
||||
|
||||
- name: 'Configure wakapi'
|
||||
ansible.builtin.import_playbook: playbook-wakapi.yml
|
||||
|
||||
- name: 'Configure wanderer'
|
||||
ansible.builtin.import_playbook: playbook-wanderer.yml
|
||||
|
||||
#
|
||||
|
||||
- name: 'Configure homepage'
|
||||
ansible.builtin.import_playbook: playbook-homepage.yml
|
||||
|
||||
- name: 'Configure transcriber'
|
||||
ansible.builtin.import_playbook: playbook-transcriber.yml
|
||||
|
||||
#
|
||||
|
||||
- name: 'Configure authelia'
|
||||
ansible.builtin.import_playbook: playbook-authelia.yml
|
||||
|
||||
- name: 'Configure caddy proxy'
|
||||
ansible.builtin.import_playbook: playbook-caddyproxy.yml
|
||||
12
playbook-all-setup.yml
Normal file
12
playbook-all-setup.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: 'Configure system'
|
||||
ansible.builtin.import_playbook: playbook-system.yml
|
||||
|
||||
- name: 'Configure docker'
|
||||
ansible.builtin.import_playbook: playbook-docker.yml
|
||||
|
||||
- name: 'Configure eget applications'
|
||||
ansible.builtin.import_playbook: playbook-eget.yml
|
||||
|
||||
- name: 'Configure backups'
|
||||
ansible.builtin.import_playbook: playbook-backups.yml
|
||||
@@ -3,15 +3,19 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
- files/authelia/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "authelia"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1011
|
||||
app_owner_gid: 1012
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
||||
|
||||
tasks:
|
||||
- name: "Create user and environment"
|
||||
@@ -19,6 +23,8 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal application directories"
|
||||
@@ -29,7 +35,10 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0700"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ config_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
- name: "Copy users file"
|
||||
ansible.builtin.copy:
|
||||
@@ -39,7 +48,7 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0600"
|
||||
|
||||
- name: "Copy configuration files (templates)"
|
||||
- name: "Copy configuration file"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/configuration.template.yml"
|
||||
dest: "{{ (config_dir, 'configuration.yml') | path_join }}"
|
||||
@@ -47,9 +56,25 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0600"
|
||||
|
||||
- name: "Copy gobackup config"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/gobackup.template.yml"
|
||||
dest: "{{ gobackup_config }}"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0640"
|
||||
|
||||
- name: "Copy backup script"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/backup.template.sh"
|
||||
dest: "{{ (base_dir, 'backup.sh') | path_join }}"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -60,8 +85,12 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
- name: "Restart application with docker compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "restarted"
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -4,13 +4,39 @@
|
||||
|
||||
vars_files:
|
||||
- vars/secrets.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
backup_config_dir: "/etc/backup"
|
||||
backup_config_file: "{{ (backup_config_dir, 'config.toml') | path_join }}"
|
||||
|
||||
restic_shell_script: "{{ (bin_prefix, 'restic-shell.sh') | path_join }}"
|
||||
backup_all_script: "{{ (bin_prefix, 'backup-all.py') | path_join }}"
|
||||
|
||||
tasks:
|
||||
- name: "Create backup config directory"
|
||||
ansible.builtin.file:
|
||||
path: "{{ backup_config_dir }}"
|
||||
state: "directory"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: "Create backup config file"
|
||||
ansible.builtin.template:
|
||||
src: "files/backups/config.template.toml"
|
||||
dest: "{{ backup_config_file }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
|
||||
- name: "Allow user to run the backup script without a password"
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/sudoers
|
||||
state: present
|
||||
line: "{{ primary_user }} ALL=(ALL) NOPASSWD: {{ backup_all_script }}"
|
||||
validate: /usr/sbin/visudo -cf %s # ВАЖНО: проверка синтаксиса перед сохранением
|
||||
create: no # Файл уже должен существовать
|
||||
|
||||
- name: "Copy restic shell script"
|
||||
ansible.builtin.template:
|
||||
src: "files/backups/restic-shell.sh.j2"
|
||||
@@ -20,8 +46,8 @@
|
||||
mode: "0700"
|
||||
|
||||
- name: "Copy backup all script"
|
||||
ansible.builtin.template:
|
||||
src: "files/backups/backup-all.template.py"
|
||||
ansible.builtin.copy:
|
||||
src: "files/backups/backup-all.py"
|
||||
dest: "{{ backup_all_script }}"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "caddyproxy"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1010
|
||||
app_owner_gid: 1011
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||
@@ -23,8 +24,9 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_extra_groups:
|
||||
- "docker"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal application directories"
|
||||
ansible.builtin.file:
|
||||
@@ -34,6 +36,7 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ config_dir }}"
|
||||
- "{{ caddy_file_dir }}"
|
||||
@@ -59,14 +62,20 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
# - name: "Reload caddy"
|
||||
# community.docker.docker_compose_v2_exec:
|
||||
# project_src: '{{ base_dir }}'
|
||||
# service: "{{ service_name }}"
|
||||
# command: caddy reload --config /etc/caddy/Caddyfile
|
||||
# - name: "Reload caddy"
|
||||
# community.docker.docker_compose_v2_exec:
|
||||
# project_src: '{{ base_dir }}'
|
||||
# service: "{{ service_name }}"
|
||||
# command: caddy reload --config /etc/caddy/Caddyfile
|
||||
# tags:
|
||||
# - run-app
|
||||
|
||||
- name: "Restart application with docker compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "restarted"
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
tasks:
|
||||
- name: "Install python docker lib from pip"
|
||||
ansible.builtin.pip:
|
||||
name: docker
|
||||
# - name: "Install python docker lib from pip"
|
||||
# ansible.builtin.pip:
|
||||
# name: docker
|
||||
|
||||
- name: "Install docker"
|
||||
ansible.builtin.import_role:
|
||||
@@ -32,3 +31,10 @@
|
||||
community.docker.docker_network:
|
||||
name: "monitoring_network"
|
||||
driver: "bridge"
|
||||
|
||||
- name: "Schedule docker image prune"
|
||||
ansible.builtin.cron:
|
||||
name: "docker image prune"
|
||||
minute: "0"
|
||||
hour: "3"
|
||||
job: "/usr/bin/docker image prune -af"
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "dozzle"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1016
|
||||
app_owner_gid: 1017
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
|
||||
tasks:
|
||||
- name: "Create user and environment"
|
||||
@@ -17,11 +18,23 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal application directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -32,3 +45,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
# See: https://github.com/zyedidia/eget/releases
|
||||
@@ -22,25 +21,42 @@
|
||||
|
||||
- name: "Install rclone"
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ eget_bin_path }} rclone/rclone --quiet --upgrade-only --to {{ eget_install_dir }} --asset zip --tag v1.71.2"
|
||||
changed_when: false
|
||||
|
||||
- name: "Install btop"
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ eget_bin_path }} aristocratos/btop --quiet --upgrade-only --to {{ eget_install_dir }} --tag v1.4.5"
|
||||
cmd: >
|
||||
{{ eget_bin_path }} rclone/rclone --quiet --upgrade-only --to {{ eget_install_dir }} --asset zip
|
||||
--tag v1.72.0
|
||||
changed_when: false
|
||||
|
||||
- name: "Install restic"
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ eget_bin_path }} restic/restic --quiet --upgrade-only --to {{ eget_install_dir }} --tag v0.18.1"
|
||||
cmd: >
|
||||
{{ eget_bin_path }} restic/restic --quiet --upgrade-only --to {{ eget_install_dir }}
|
||||
--tag v0.18.1
|
||||
changed_when: false
|
||||
|
||||
- name: "Install btop"
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
{{ eget_bin_path }} aristocratos/btop --quiet --upgrade-only --to {{ eget_install_dir }}
|
||||
--tag v1.4.5
|
||||
changed_when: false
|
||||
|
||||
- name: "Install gobackup"
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ eget_bin_path }} gobackup/gobackup --quiet --upgrade-only --to {{ eget_install_dir }} --tag v2.15.3"
|
||||
cmd: >
|
||||
{{ eget_bin_path }} gobackup/gobackup --quiet --upgrade-only --to {{ eget_install_dir }}
|
||||
--tag v2.17.0
|
||||
changed_when: false
|
||||
|
||||
- name: "Install task"
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ eget_bin_path }} go-task/task --quiet --upgrade-only --to {{ eget_install_dir }} --asset tar.gz --tag v3.45.4"
|
||||
cmd: >
|
||||
{{ eget_bin_path }} go-task/task --quiet --upgrade-only --to {{ eget_install_dir }} --asset tar.gz
|
||||
--tag v3.45.5
|
||||
changed_when: false
|
||||
|
||||
- name: 'Install dust'
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
{{ bin_prefix }}/eget bootandy/dust --quiet --upgrade-only --to {{ bin_prefix }} --asset gnu
|
||||
--tag v1.2.3
|
||||
changed_when: false
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "gitea"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1005
|
||||
app_owner_gid: 1006
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
|
||||
@@ -19,10 +20,9 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_extra_groups:
|
||||
- "docker"
|
||||
owner_ssh_keys:
|
||||
- "{{ lookup('file', 'files/av_id_rsa.pub') }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal application directories"
|
||||
ansible.builtin.file:
|
||||
@@ -32,6 +32,7 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
@@ -56,3 +57,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "gramps"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1009
|
||||
app_owner_gid: 1010
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
media_dir: "{{ (base_dir, 'media') | path_join }}"
|
||||
cache_dir: "{{ (base_dir, 'cache') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
||||
|
||||
@@ -20,10 +23,9 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_extra_groups:
|
||||
- "docker"
|
||||
owner_ssh_keys:
|
||||
- "{{ lookup('file', 'files/av_id_rsa.pub') }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create application internal directories"
|
||||
ansible.builtin.file:
|
||||
@@ -33,12 +35,15 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ media_dir }}"
|
||||
- "{{ cache_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
- name: "Copy gobackup config"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/gobackup.yml.j2"
|
||||
src: "./files/{{ app_name }}/gobackup.template.yml"
|
||||
dest: "{{ gobackup_config }}"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -46,15 +51,36 @@
|
||||
|
||||
- name: "Copy backup script"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/backup.sh.j2"
|
||||
src: "files/{{ app_name }}/backup.template.sh"
|
||||
dest: "{{ base_dir }}/backup.sh"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
|
||||
- name: "Create backup targets file"
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ base_dir }}/backup-targets"
|
||||
line: "{{ item }}"
|
||||
create: true
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ data_dir }}"
|
||||
- "{{ media_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
- name: "Copy rename script"
|
||||
ansible.builtin.copy:
|
||||
src: "files/{{ app_name }}/gramps_rename.py"
|
||||
dest: "{{ base_dir }}/gramps_rename.py"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -65,3 +91,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
20
playbook-homepage-registry.yml
Normal file
20
playbook-homepage-registry.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: "Upload local homepage images to registry"
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
|
||||
vars_files:
|
||||
- vars/secrets.yml
|
||||
- vars/homepage.yml
|
||||
- vars/homepage.images.yml
|
||||
|
||||
tasks:
|
||||
|
||||
- name: "Push web service image to remote registry"
|
||||
community.docker.docker_image:
|
||||
state: present
|
||||
source: local
|
||||
name: "{{ homepage_nginx_image }}"
|
||||
repository: "{{ registry_homepage_nginx_image }}"
|
||||
push: true
|
||||
delegate_to: 127.0.0.1
|
||||
@@ -1,60 +1,39 @@
|
||||
---
|
||||
# Play 1: Setup environment for the application
|
||||
- name: "Setup environment for homepage application"
|
||||
- name: "Setup and deploy homepage service"
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
- vars/homepage.yml
|
||||
tags:
|
||||
- setup
|
||||
- vars/homepage.images.yml
|
||||
|
||||
tasks:
|
||||
- name: "Create user and environment"
|
||||
ansible.builtin.import_role:
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_extra_groups:
|
||||
- "docker"
|
||||
owner_ssh_keys:
|
||||
- "{{ lookup('file', 'files/av_id_rsa.pub') }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create application internal directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
|
||||
- name: "Login to yandex docker registry."
|
||||
ansible.builtin.script:
|
||||
cmd: "files/yandex-docker-registry-auth.sh"
|
||||
|
||||
# Play 2: Deploy the application
|
||||
- name: "Deploy homepage application"
|
||||
hosts: all
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
- vars/homepage.yml
|
||||
tags:
|
||||
- deploy
|
||||
tasks:
|
||||
- name: "Check is web service image passed"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "homepage_web_image is defined"
|
||||
fail_msg: 'You must pass variable "homepage_web_image"'
|
||||
|
||||
- name: "Create full image name with container registry"
|
||||
ansible.builtin.set_fact:
|
||||
registry_homepage_web_image: "{{ (docker_registry_prefix, homepage_web_image) | path_join }}"
|
||||
|
||||
- name: "Push web service image to remote registry"
|
||||
community.docker.docker_image:
|
||||
state: present
|
||||
source: local
|
||||
name: "{{ homepage_web_image }}"
|
||||
repository: "{{ registry_homepage_web_image }}"
|
||||
push: true
|
||||
delegate_to: 127.0.0.1
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -65,3 +44,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
82
playbook-memos.yml
Normal file
82
playbook-memos.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
- name: "Configure memos application"
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "memos"
|
||||
app_user: "{{ app_name }}"
|
||||
app_owner_uid: 1019
|
||||
app_owner_gid: 1020
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
||||
|
||||
tasks:
|
||||
- name: "Create user and environment"
|
||||
ansible.builtin.import_role:
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create application internal directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
- name: "Copy gobackup config"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/gobackup.yml.j2"
|
||||
dest: "{{ gobackup_config }}"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0640"
|
||||
|
||||
- name: "Copy backup script"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/backup.sh.j2"
|
||||
dest: "{{ base_dir }}/backup.sh"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
|
||||
- name: "Create backup targets file"
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ base_dir }}/backup-targets"
|
||||
line: "{{ item }}"
|
||||
create: true
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ data_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0640"
|
||||
|
||||
- name: "Run application with docker compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "miniflux"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1013
|
||||
app_owner_gid: 1014
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
secrets_dir: "{{ (base_dir, 'secrets') | path_join }}"
|
||||
postgres_data_dir: "{{ (base_dir, 'data', 'postgres') | path_join }}"
|
||||
@@ -21,6 +22,8 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal directories"
|
||||
@@ -31,6 +34,10 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ secrets_dir }}"
|
||||
- "{{ postgres_data_dir }}"
|
||||
- "{{ postgres_backups_dir }}"
|
||||
|
||||
- name: "Copy secrets"
|
||||
@@ -50,7 +57,7 @@
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -58,7 +65,7 @@
|
||||
|
||||
- name: "Copy backup script"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/backup.sh.j2"
|
||||
src: "./files/{{ app_name }}/backup.template.sh"
|
||||
dest: "{{ base_dir }}/backup.sh"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -70,3 +77,5 @@
|
||||
state: "present"
|
||||
recreate: "always"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "netdata"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1012
|
||||
app_owner_gid: 1013
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||
config_go_d_dir: "{{ (config_dir, 'go.d') | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
@@ -20,6 +21,8 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal application directories"
|
||||
@@ -30,13 +33,14 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ config_dir }}"
|
||||
- "{{ config_go_d_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
|
||||
- name: "Copy netdata config file"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/netdata.conf.j2"
|
||||
src: "files/{{ app_name }}/netdata.template.conf"
|
||||
dest: "{{ config_dir }}/netdata.conf"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -82,7 +86,7 @@
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -93,8 +97,12 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
- name: "Restart application with docker compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "restarted"
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "outline"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1007
|
||||
app_owner_gid: 1008
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
postgres_data_dir: "{{ (base_dir, 'data', 'postgres') | path_join }}"
|
||||
postgres_backups_dir: "{{ (base_dir, 'backups', 'postgres') | path_join }}"
|
||||
@@ -20,10 +21,9 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_extra_groups:
|
||||
- "docker"
|
||||
owner_ssh_keys:
|
||||
- "{{ lookup('file', 'files/av_id_rsa.pub') }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal directories"
|
||||
ansible.builtin.file:
|
||||
@@ -33,11 +33,14 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ postgres_data_dir }}"
|
||||
- "{{ postgres_backups_dir }}"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -45,7 +48,7 @@
|
||||
|
||||
- name: "Copy backup script"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/backup.sh.j2"
|
||||
src: "./files/{{ app_name }}/backup.template.sh"
|
||||
dest: "{{ base_dir }}/backup.sh"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
@@ -56,3 +59,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "rssbridge"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1014
|
||||
app_owner_gid: 1015
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
|
||||
tasks:
|
||||
- name: "Create user and environment"
|
||||
@@ -17,8 +18,20 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create internal application directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
@@ -32,3 +45,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
@@ -40,3 +39,20 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: 'Create directory for mount'
|
||||
ansible.builtin.file:
|
||||
path: '/mnt/applications'
|
||||
state: 'directory'
|
||||
mode: '0755'
|
||||
tags:
|
||||
- mount-storage
|
||||
|
||||
- name: 'Mount external storages'
|
||||
ansible.posix.mount:
|
||||
path: '/mnt/applications'
|
||||
src: 'UUID=3942bffd-8328-4536-8e88-07926fb17d17'
|
||||
fstype: ext4
|
||||
state: mounted
|
||||
tags:
|
||||
- mount-storage
|
||||
|
||||
20
playbook-transcriber-registry.yml
Normal file
20
playbook-transcriber-registry.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: "Upload local transcriber images to registry"
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
|
||||
vars_files:
|
||||
- vars/secrets.yml
|
||||
- vars/transcriber.yml
|
||||
- vars/transcriber.images.yml
|
||||
|
||||
tasks:
|
||||
|
||||
- name: "Push web service image to remote registry"
|
||||
community.docker.docker_image:
|
||||
state: present
|
||||
source: local
|
||||
name: "{{ transcriber_image }}"
|
||||
repository: "{{ registry_transcriber_image }}"
|
||||
push: true
|
||||
delegate_to: 127.0.0.1
|
||||
@@ -3,25 +3,9 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
|
||||
vars:
|
||||
app_name: "transcriber"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
|
||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||
config_file: "{{ (config_dir, 'config.toml') | path_join }}"
|
||||
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
|
||||
docker_registry_prefix: "cr.yandex/crplfk0168i4o8kd7ade"
|
||||
|
||||
# transcriber_image: "{{ transcriber_image | default(omit) }}"
|
||||
|
||||
- vars/transcriber.yml
|
||||
- vars/transcriber.images.yml
|
||||
|
||||
tasks:
|
||||
- name: "Create user and environment"
|
||||
@@ -29,6 +13,8 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create application internal directories"
|
||||
@@ -39,6 +25,7 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ config_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
@@ -55,38 +42,18 @@
|
||||
ansible.builtin.script:
|
||||
cmd: "files/yandex-docker-registry-auth.sh"
|
||||
|
||||
- name: "Deploy service"
|
||||
when: transcriber_image is defined
|
||||
block:
|
||||
# - name: "Check is web service image passed"
|
||||
# ansible.builtin.assert:
|
||||
# that:
|
||||
# - "transcriber_image is defined"
|
||||
# fail_msg: 'You must pass variable "transcriber_image"'
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.template.yml"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0640"
|
||||
|
||||
- name: "Create full image name with container registry"
|
||||
ansible.builtin.set_fact:
|
||||
registry_transcriber_image: "{{ (docker_registry_prefix, transcriber_image) | path_join }}"
|
||||
|
||||
- name: "Push web service image to remote registry"
|
||||
community.docker.docker_image:
|
||||
state: present
|
||||
source: local
|
||||
name: "{{ transcriber_image }}"
|
||||
repository: "{{ registry_transcriber_image }}"
|
||||
push: true
|
||||
delegate_to: 127.0.0.1
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
src: "./files/{{ app_name }}/docker-compose.yml.j2"
|
||||
dest: "{{ base_dir }}/docker-compose.yml"
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0640"
|
||||
|
||||
- name: "Run application with docker compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
- name: "Run application with docker compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
tasks:
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "wakapi"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1015
|
||||
app_owner_gid: 1016
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
||||
@@ -20,6 +21,8 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create application internal directories"
|
||||
@@ -30,6 +33,7 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ backups_dir }}"
|
||||
|
||||
@@ -62,3 +66,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
hosts: all
|
||||
|
||||
vars_files:
|
||||
- vars/ports.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
app_name: "wanderer"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1018
|
||||
app_owner_gid: 1019
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
gobackup_config: "{{ (base_dir, 'gobackup.yml') | path_join }}"
|
||||
@@ -23,6 +24,8 @@
|
||||
name: owner
|
||||
vars:
|
||||
owner_name: "{{ app_user }}"
|
||||
owner_uid: "{{ app_owner_uid }}"
|
||||
owner_gid: "{{ app_owner_gid }}"
|
||||
owner_extra_groups: ["docker"]
|
||||
|
||||
- name: "Create application internal directories"
|
||||
@@ -33,6 +36,7 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ base_dir }}"
|
||||
- "{{ data_dir }}"
|
||||
- "{{ (data_dir, 'pb_data') | path_join }}"
|
||||
- "{{ (data_dir, 'uploads') | path_join }}"
|
||||
@@ -47,13 +51,29 @@
|
||||
group: "{{ app_user }}"
|
||||
mode: "0640"
|
||||
|
||||
- name: "Copy backup script"
|
||||
ansible.builtin.template:
|
||||
src: "files/{{ app_name }}/backup.template.sh"
|
||||
# - name: "Copy backup script"
|
||||
# ansible.builtin.template:
|
||||
# src: "files/{{ app_name }}/backup.template.sh"
|
||||
# dest: "{{ base_dir }}/backup.sh"
|
||||
# owner: "{{ app_user }}"
|
||||
# group: "{{ app_user }}"
|
||||
# mode: "0750"
|
||||
|
||||
- name: "Disable backup script"
|
||||
ansible.builtin.file:
|
||||
dest: "{{ base_dir }}/backup.sh"
|
||||
state: absent
|
||||
|
||||
- name: "Create backup targets file"
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ base_dir }}/backup-targets"
|
||||
line: "{{ item }}"
|
||||
create: true
|
||||
owner: "{{ app_user }}"
|
||||
group: "{{ app_user }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ data_dir }}"
|
||||
|
||||
- name: "Copy docker compose file"
|
||||
ansible.builtin.template:
|
||||
@@ -68,3 +88,5 @@
|
||||
project_src: "{{ base_dir }}"
|
||||
state: "present"
|
||||
remove_orphans: true
|
||||
tags:
|
||||
- run-app
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
# defaults file for eget
|
||||
eget_version: "1.3.4"
|
||||
eget_download_url: "https://github.com/zyedidia/eget/releases/download/v{{ eget_version }}/eget-{{ eget_version }}-linux_amd64.tar.gz"
|
||||
eget_download_url: "https://github.com/zyedidia/eget/releases/download/v{{ eget_version }}/eget-{{ eget_version }}-linux_amd64.tar.gz" # yamllint disable-line rule:line-length
|
||||
eget_install_path: "/usr/bin/eget"
|
||||
|
||||
eget_download_dest: '/tmp/{{ eget_download_url | split("/") | last }}'
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
owner_name: ""
|
||||
owner_uid: 0
|
||||
owner_group: "{{ owner_name }}"
|
||||
owner_gid: "{{ owner_uid }}"
|
||||
owner_extra_groups: []
|
||||
owner_ssh_keys: []
|
||||
owner_env: {}
|
||||
|
||||
@@ -4,9 +4,15 @@
|
||||
msg: You must set owner name.
|
||||
when: not owner_name
|
||||
|
||||
- name: 'Check app requirements for user "{{ owner_name }}".'
|
||||
ansible.builtin.fail:
|
||||
msg: You must set owner uid.
|
||||
when: not owner_uid
|
||||
|
||||
- name: 'Create group "{{ owner_group }}".'
|
||||
ansible.builtin.group:
|
||||
name: "{{ owner_group }}"
|
||||
gid: "{{ owner_gid }}"
|
||||
state: present
|
||||
|
||||
- name: 'Create user "{{ owner_name }}".'
|
||||
@@ -14,6 +20,7 @@
|
||||
name: "{{ owner_name }}"
|
||||
group: "{{ owner_group }}"
|
||||
groups: "{{ owner_extra_groups }}"
|
||||
uid: "{{ owner_uid }}"
|
||||
shell: /bin/bash
|
||||
register: user_create_result
|
||||
|
||||
|
||||
2
vars/homepage.images.yml
Normal file
2
vars/homepage.images.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
homepage_nginx_image: "homepage-nginx:f797e17-1761204003"
|
||||
@@ -1,7 +1,10 @@
|
||||
---
|
||||
app_name: "homepage"
|
||||
app_user: "{{ app_name }}"
|
||||
base_dir: "/home/{{ app_user }}"
|
||||
app_owner_uid: 1008
|
||||
app_owner_gid: 1009
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
docker_registry_prefix: "cr.yandex/crplfk0168i4o8kd7ade"
|
||||
|
||||
homepage_web_image: "{{ homepage_web_image | default(omit) }}"
|
||||
# Registry images
|
||||
registry_homepage_nginx_image: "{{ (docker_registry_prefix, homepage_nginx_image) | path_join }}"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
base_port: 41080
|
||||
homepage_port: "{{ base_port + 3 }}"
|
||||
netdata_port: "{{ base_port + 4 }}"
|
||||
gitea_port: "{{ base_port + 8 }}"
|
||||
outline_port: "{{ base_port + 10 }}"
|
||||
gramps_port: "{{ base_port + 12 }}"
|
||||
308
vars/secrets.yml
308
vars/secrets.yml
@@ -1,148 +1,162 @@
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
30613835326461383435616166303666393830306434363432623438383036636133653237373539
|
||||
6433373530386638376563396362383833653139343930360a343766386664336165326233633235
|
||||
62313037383837373432363138383639333531666264666631313634386162653764643235383363
|
||||
3261633539303538620a643434316631643866623737613038626534656331643038366638383531
|
||||
31353139613634363861396566386631626139313465306463333831653564393837313865333532
|
||||
35663134376634313833636433646165383931393464636631333362353064333063393962656266
|
||||
63303362646631313565636631333764613635303663386465633263633734356536646631313130
|
||||
61613733383931306361333237623933323436363061333432666434393836356537376233333936
|
||||
65366561343564353336376332656334653630366362396661636161663262313831373234623931
|
||||
36383333656562376462366632643137303633646165663134323837373735343964323164633434
|
||||
66393137336632663932623764633363653365666231636536636438393936373565656130646136
|
||||
62373036623231356164383365363537363463653834663961313164386662636530646466326437
|
||||
30303130313863306431393431346266333332333664636430303033663234616366343262353835
|
||||
39333562646331653962356364303564393839316234613266373832326539613432346533646235
|
||||
64613862373635373066323139616236303532393131393962373638323234643361613131306366
|
||||
31336235346165633830386138363035323635353630623939383138383632386662393239383033
|
||||
66646235393731623434613064336163643938353933346331333730386262373739653965346136
|
||||
33346339666139646434383933653638326632626435656432613833666464356364383863353665
|
||||
64383939333933393261613665616638656563666366313737616533613037336663643234313736
|
||||
63346435323630376565626263646236373738663131633033313265616364353961613836653861
|
||||
39343862663665306638646366346466333835393735343765653764363830346435323632306237
|
||||
62373634626432663436613162303431666131623133626637346235353366313933323436326239
|
||||
34313531333439653633356637373131383134616165303165383533336561356339353366373431
|
||||
33323237653636323464343431663831633735333436663565313139376164303665316465353061
|
||||
36353336396361646431343761346665393531636432343433306462353462313134343637636336
|
||||
35333862643864323233353534616663643034383735303733393661633865666630623763393963
|
||||
39663136666166626339626235393131646638356138353461636531646537366535383731663831
|
||||
36656361313838616364623530633764623439373764323539386662613365623438336638623133
|
||||
34326334313662663765643132393961656165656464353964663132643061376135386364316137
|
||||
39313835653530636466326136383537616330633065353665343839656462623466646362613462
|
||||
35626134353838656664393863333935386264363266353065323937666261363664623836393030
|
||||
35626636303132636464643263366163383837303837303738386331313934653431623737323463
|
||||
32646562373230393930623136623363313461666564313664373963316163363338323262653263
|
||||
38316466363636313137636333393430333565626264326536626162316630633165666139653335
|
||||
37666537646636316239653762653633623333303035363737333665613232323864626634303164
|
||||
61633334623465326335653334396439633331373935303862356136653266613536643966393139
|
||||
34633263313734663832383864363962313166366230656562383462663734646133666637363239
|
||||
64393864616162336662386432626237626463326133326464343935303436623165616166396561
|
||||
39313665613331663037626363623931366563646664646263633339346236393362303232303035
|
||||
31333233343238336263633266653339313638323563306466376230653633656562656537343962
|
||||
63323562646638643363326530616239613737666634643332623131366564376365666663376434
|
||||
30346533343065656531663862323666313030393063626231636462356534666539653065643862
|
||||
30303165333465636264336463346461383665613663613764353661623139363138383365343430
|
||||
63323565666565643737333733316534626561663362383065313839363463373030393430636663
|
||||
31343939363633663261323463643465636635316565663464393133656461303163376562613730
|
||||
65666466316530663465313936663538376436613238616639623564313837333763363030393633
|
||||
32666664626463383232646636663066333335613564303561653332656262353235643564373765
|
||||
35656665333135323439343732643137656536346634326166633534616437316661643262336533
|
||||
34313530666534303639316634346366633434633764643233393730373164393166333038393130
|
||||
30313136333635623964386533343934313831343063386433623963376565306165666165626535
|
||||
36656562356365343033383036666366333639373761303134666465323834336462636466316632
|
||||
64333964383932363362356431303134353162383839323833393266613935636461663833636135
|
||||
63336262396238316630326535306139363862313730393035626338316631663434336232326431
|
||||
63386434386433303039646436366134383262336532636533666632653563343939323161623033
|
||||
65623334386631346337613833663031656261373162613838326334616261663565313862363439
|
||||
38643739383762363432383938616235396333656533313635656363626433616637656235653566
|
||||
62643031343030363930616464643631313532363133306363613733656363666232316639343464
|
||||
30363837366261343266366535613636363963343837656439343331656462326135366131356232
|
||||
63616337373431616135373131653566636333623561373933613864626631643933316661336230
|
||||
61373762366361613965633334343630613464663138653761623531333336363634326534646631
|
||||
37393163373636353763313061623338646639386435363434656662393336313930343666616561
|
||||
36306138663266353837376163623531326237383063653139613431323561363163343637393234
|
||||
61666664616365306533623730663832376639353761396337353333346433663033356438383262
|
||||
33353562366537366561663565663835646536376162626165326333323135376338623663383963
|
||||
65666361663534363666663162616466653938356537613334633237306338636533313637653836
|
||||
33333932623433663064366365333761663835636464613963356565346633623761386334386261
|
||||
35666363313564376135313238303064346132333736633566373438653234353138383763656338
|
||||
66343434326430663139343139333364623936396363633634653135323635656264353131336464
|
||||
61396236306266356439616139303533303435633062356333363336363838623733663030363862
|
||||
61383234376237376361333965386532326665656634346433653033626236393866623162393539
|
||||
61633538343731316666363537356531373962666338326138623836663631353337346434373262
|
||||
34623234366632656331383263643933613465313233373663643166613334386663303761353936
|
||||
65323664633430363866333165386564343662376135323561343138663266393064326135386364
|
||||
65363036303766633131653732333937633364643934623361656132343739613433393163396438
|
||||
33393831396330323333343466333834613134636236663638333461643034363436373730343565
|
||||
38396566323433373836393764356236666265303863373866656233333337653866383534656435
|
||||
36346634633263363633646539316463313965396466346638666266633432653539653165396639
|
||||
36633962623965363266376535306366346664633365343737373163623438656563316238346236
|
||||
39306538386366306637326235306165623663613564633463616330373564373534336265633039
|
||||
39366531666538616165626130383265353364393765353839633339303236346263643530376137
|
||||
64346133336430383732376133643465366530313233343965643563383866373639636335336530
|
||||
35306566663362366364653032643032626665663865346532376431646163616261356235333163
|
||||
36646366613566643239386639623233323963613930373962346535366261303464313235633137
|
||||
33353463636637316434356331303730383863353035393365633261346264316633376638626333
|
||||
30336561326635333966623537323931383261323337623337613936386638376565326230386335
|
||||
62616332653466656437626331633734646131393932646637323335656237616261656562396633
|
||||
33316363396338386332623338313361356439383435633633643538313764393132333230633363
|
||||
32653836316638396265353036356461646665666336336230333666663234326465396135333939
|
||||
61303339383239363631376662346563613962313364663437613261363065653934376661323464
|
||||
35363731613563626133383763613962396366666266633064333962313331663338663265313731
|
||||
39663633613239383338386530373536643266663462643362343061663462653332393533373130
|
||||
39396230306365346636303963383538653564356563386364663465326536623962333335393961
|
||||
62323564323434623631373163346234663964303738373035613361636532346535646466323631
|
||||
65366663323136653064396131613634643832346137326138656439316330366665636362316330
|
||||
31636365343865663837336634363134313436393035666533373435363933343766356361663765
|
||||
64613966646238663033613637316535653163626430393337643662636462393139636334366539
|
||||
63616333323930313863393735653966336237393535343939633366353130633332373032373366
|
||||
35336562396661616261663731383939343961353135626338353734306634356331333539393663
|
||||
36313362303432643934303239326365623335393031306164633235313634343936643064386236
|
||||
38326436653664326533323530313338303335613933663435633035653365646436333633373363
|
||||
34633334663765386531346365313132656139626137353666623865663465663066376532363161
|
||||
33326565393838313537353636383266313438363734373632343134353134616536373061316634
|
||||
64323861396362666638313635633465393932313136633538633839313431383762373664656666
|
||||
61613232613563396334323934626630636166613465373638323436313439336461666264346166
|
||||
34643666623965346664316531326335343063393334353262346535323333303962653562346335
|
||||
33636232623861666535663333336639363930303836366435396165333832366463326435613939
|
||||
66663938313863303037316663366430323532333532343339646230336666396633616639626361
|
||||
36336664663333363563613461323031613734636465363862346466353132393436323764656466
|
||||
31306238623462383230396237643439336364643464633839343732653936323438366339393565
|
||||
64383665366362633834663233636131646461653733633138326132616565653134663762333036
|
||||
64346561303034653136313962356666383639646436666463346562386333366462376134373265
|
||||
31373733376238643138633236353832626362323466333661396562363565306463643862346666
|
||||
36626561393364306330623961386161616236636134663563623066366462616564663434616430
|
||||
31633531366238636634333765353531626562313561363031666536323730303562383539336262
|
||||
62613433643538353032666336666234303466646337656334363630393564393966343061396331
|
||||
35663033646135356665303862623831653936626463623332303365363335623766396538333263
|
||||
39346265313664306534316435343334393830656334396134333464663663333930316538323439
|
||||
65613132373237396464373738656663643066393630666634303434373138353936626633336661
|
||||
37326334616538313566313762356435363135346635643236323830316563343134313839626237
|
||||
34306532646537636266663963303464383130313664323236386363303234643838666566363332
|
||||
36663636363861616566303834333430663261643334666534663635663532613031623230666466
|
||||
65363536383737623262623363646232623333366336346363333161323139396339306261323935
|
||||
34396431343031306533633337303965393730343839633336316637386137363537383831396134
|
||||
33653162613636393634326633343966303839393033663039643532313938313461666634376461
|
||||
37653333613437666134646363643833633532393461633133373231393931646362313536353861
|
||||
39663662346332353637386364303037366333373264356565383966376464346337306565613235
|
||||
61356533353833663461626333383434303335643462653461363362396332353436333165343134
|
||||
31663634386533393733643934636536313765373332643961356237366637623934393638323536
|
||||
36363631323130643737623033636530393532653064613734336639663730353461306236636637
|
||||
66383139363266616339653335376432313166613930343061343631666235343837343663393438
|
||||
33623561623366626434363231373132336262326566333538613762396433303136366633323565
|
||||
63383138373830313036363338366366336537366536306632313834666532386661393265343236
|
||||
34333364376461636333613963633166643638363364326137303966386432346534643632333762
|
||||
31333131613063323332616232643866393963363466326538383562323636613539643532636330
|
||||
66396230393132343064376435346537306533343531323864366162653162306533633637363830
|
||||
61313234373538356462366132636565376633313638316337336135346662353039356436393031
|
||||
33316537653262363839353537636232646361333932323131633731303932303361386636353131
|
||||
66383235376263633763303731613234643261623337323364626363323437346637343631616430
|
||||
37613135303764373235346464343737393933323966333032386638323734646134666631626564
|
||||
62643333616539343535643764313062313466316331306139646164346163666333313538393464
|
||||
36363563323865386665643731303535656236636131343363616239326630623230393132386339
|
||||
66643664616532373463626664363632623838316137613537353532396131353731386137646263
|
||||
36653234313461323032636135353535646665343133313331313164643038313831653065366466
|
||||
34366437366539613033356135666138383062373565303365353461373766373534333539343732
|
||||
35306530396138303065613866326365303661363637613035353638396263663936336132346664
|
||||
30646239623362303334386636623831666533326461323466383639376462653632646366363133
|
||||
373165643236666232623839376534373231
|
||||
66333736306664316131646233393639356436323832386638353237393761386631303639396432
|
||||
6266616434663638306637356435393564303633613332640a663366336135373061396239653065
|
||||
32343339313734346261363461633735383538613033656138383835653661633334316533613738
|
||||
3730656661393466370a653863353234323739346630323534333334306432646636383664313865
|
||||
39666133623032393638633239653665376336626638303334626164376663626666393439346661
|
||||
32363364363066653933313135666566346138353163333639353062336331623938353131646334
|
||||
32326466323030643364356530653862633332363338333633393730663536353363663165303838
|
||||
66643331366231613733316139333233393636626162643861346437613062643133353035353566
|
||||
38323062653135393364376265346361613163346337636634383932666137636133363864643264
|
||||
39646634363037383662376166633335636365303734646465623833313766656235333835396263
|
||||
63326237306337396465343065313263663466613336303934373337623364613839323931623934
|
||||
35353665363339646365353139643032366164653133616562303930306264343633343439373830
|
||||
66356635343363363361313633353134313837653163346537656465623832633561323833663763
|
||||
32323537303931343934376165663466356466333533643237653038373866626439356334663539
|
||||
36613336326633306331323763393230653236306337353139353135316566336661623464316237
|
||||
37363930666539373837336466333265333866633733363032323862333239643764333766366134
|
||||
33396330613463633261626334393262343031663131313737623233323535303965333864366631
|
||||
65333535343062393434396361313433386463613630353765663363633431393831316233313162
|
||||
39656333306265386437663863343638323262663734623830336562636366333534373735313932
|
||||
61653739616635643661306165363364316262386434643033646430366235303334326236373262
|
||||
34396261653934633337646338333364326237663739623965313039303134393238653634616431
|
||||
39376539323238353033323333643337613935616335336562626361383164616432633331313536
|
||||
63373633633966373237393131663064613332316536373163303163653638343264323934393365
|
||||
62356636643434646465313734363936346435663237393064663138643135303237633965393965
|
||||
31353564616136366237666139646561363364353738633862346262616637663362333137386133
|
||||
63383662363866306366326232643462376532313632336662666666386562356436616236663430
|
||||
37636661656237646431616331633833306266313434326461353561643835646236346539323337
|
||||
30303065313165306233646135363766613931383433313165366662636137326162633363306431
|
||||
31626564323566313036363666386338366462613164663735363333313830306238323365363737
|
||||
65333137363631623139333964316464376662643661643038326162643630323938626332633130
|
||||
62626334666131373731343432303461656537303062396638326134356166663936663364656139
|
||||
32333864653231636235663165323936626135313838663866373132376437656236363235353533
|
||||
39346532626666656233343433383434613238653833626436643566653462346330316565366564
|
||||
33623831643265623966326638656462306161636366303266333734396433653861393363333332
|
||||
61616463613931393835613463353039646164383435373330626134376339623861396266623430
|
||||
30316365356337356531363263623362633332313536373333653964356534623861613232653932
|
||||
35613064336131313632656663303631363664366163343362643365663932356138376235313466
|
||||
30353333376461623435363931356665306333623736313562333836336563616137633863346635
|
||||
37356137306361383134663535626130646135363661353438343961653766333538353330346236
|
||||
64326639383864396336343062663965343964396162386266363639643962666431336237303864
|
||||
66663861346139363335663362333032613637336266323439366566373136643133383361323061
|
||||
37633134323933613665366665383962373935646137616139353661336665613661623834303465
|
||||
30323264333137636261393535376438363134663734313662383533313130623365386335323662
|
||||
63366139643238613632326165313835363964336237383936333737646239363365623030666364
|
||||
64656432653164643565376666373262333839353139666561623731343234326637316636333765
|
||||
63306331343538386433376566326239376232363434343838653864393562383063663566333263
|
||||
35326333326462316134383139303534343263646530363266663933353834353138303435646339
|
||||
33643361363062373735663430346636333431363736373463326439353437356530373935633962
|
||||
63333031376163656565663536366230333731613833396266383465333461386161373337323863
|
||||
36313032613534346230636566383930656330656133376431376462656536386263343831393862
|
||||
32363365623061653837303736636664663361663862656562393661623330386435646336373531
|
||||
35363037356638653831386261646235613337363066343632653632306631633138633235356139
|
||||
39663936333262643061646330316538373862353030626632396336393030643239316634343730
|
||||
35363564373865376533333466666439646633313932656665383930623531633038316363636332
|
||||
37363466643835353132333532646163316636303662646234613038333334626365623964653235
|
||||
36393739353164306666313537633538383934363330373235353262616165623132613330303735
|
||||
65323362666263653937376562633833653264613439303236373466646362316462386632373038
|
||||
35353462633730666430623638626439626364616335643964623933663233376433353233633235
|
||||
34616233636335323365646538326639383033643832323139633064616635353331376230663738
|
||||
35316665616230633335366233363332353432633937653335316662306166383337633262633634
|
||||
35303766653733376362623436383663663437393461643266376530613533383038373035356234
|
||||
32343962623930336566363164616361386134376362383138653963366339326431653832393664
|
||||
66633566343666326339323536343738396532623735343034646130386332323466346365383135
|
||||
33373732363833316138343938633262373066613930343162663163323331373466366631626237
|
||||
34623062353139353734653366313363323634346564663861613233366537663732363134643638
|
||||
65623964396665303765343430623636376637666364363835346462613763306135326463353631
|
||||
33333834333464383437336531616662643461666138383435636530373761646564626438313433
|
||||
64643037626637343433366631343266373436343864396663353039333231646462333932353436
|
||||
33643837616639666363353237313137353133346636383231623634326335386537363030613537
|
||||
33306333363638643533373237633833663333393566656466313832383636663031663433636663
|
||||
37313034353734343966613934663530643537366562623137373331623632653466333839376331
|
||||
61623866633937666365633763613138346365393934383163623730373134373531616138363733
|
||||
65616230303337396561666462653866333438353463316235303331643834653165363033626537
|
||||
37386636653337363666393163393031333461383331613965303262616530363133373732313362
|
||||
33343033373963656333363064303035666663646536373764323833653037316231316430333634
|
||||
65383236663035326636336535636462323438363165633437333337613439326433626466396365
|
||||
38393362633266663962646565336539333239346133323434646632643537613435643434623631
|
||||
63636536393936343165393966663438343261333966363639323462663566613437393838323036
|
||||
33393163323034336533333632646230343138336333353236376136383664646466626666356234
|
||||
61653466363933333331613539636431393934393235376433326665643263663638306463393837
|
||||
34396339383536636461366230383938386339303334393038343239363361666565336237326465
|
||||
63623231663861303436353533663661656431646165646662383065386362636633333631643335
|
||||
38373464373432626538616234623638303734626237393566326463633765316365653837303433
|
||||
34376438323439633237313733343836343733373930643138636333366166353666373966323231
|
||||
63613466306365386137336538613837613264633735393937343166303736396162303230623430
|
||||
33363233663761333063363134393935333530343133303138373934666236393732396330643438
|
||||
61343231666363323834346132376135303339313766383365363837313163393636333563376436
|
||||
64333832393361626663376161343033383763373537396264646239303736333263303739326436
|
||||
31393665363734323364643032393031313135623563383639316163616535323938343765356264
|
||||
35616433396236396662393930646431643063323163343366313030383766323733333865616235
|
||||
65623737663763373363613030326665613333636366393464383139626462346333323162333537
|
||||
32386635636532346539623534346364623532656435653638643962353836653330316638633661
|
||||
38363330656161393766383237663737663835646565363966373563663832313263633238316165
|
||||
64643536336232396436636261303866376132366261373132333631646166393764636130326335
|
||||
39613037633239626666396262386533343764623233626335373139663937613433356134633330
|
||||
32656138383563343734616536303265306661386362343939626332623763393136323138653937
|
||||
39646537366461353364616538663361663465626634356338323166373837323339343061323261
|
||||
33393765653034643166313639323962306265383336663265623832393038386334643661336663
|
||||
66643330306239383736636330393266346537326436663432653031303765393930633761343363
|
||||
61353163323830656538373366323230353830633534326133613861356132623938663565393130
|
||||
63333764613761663162633035353036663736656138623234313833326337316438323835313465
|
||||
31653136356638623965363266636461646465313065666137313931623063303337393963353437
|
||||
39633166326662303834303261353965363235626535643564613064306636366461666263383833
|
||||
66363966636538373435323365636630383561336533356631646563646536383333393864613164
|
||||
38393638623263666239623835613933393564323132373630623734363334663735633438663137
|
||||
35613563356161316632323562626639633931643762643232636136653731323337333236326363
|
||||
36633338386230626665373666643831626132323866653430393531336466386463663865393962
|
||||
37363633343632653963306531393537633762313565303631643064363531363839643363356139
|
||||
33666162306331393237333966643735643731633331373839356637636462633836633762653039
|
||||
32633630303437633130613366386633346637623266663361656365633737346432343263646536
|
||||
35376433386464383533323231353830666363363437623033643238363438303565616137316461
|
||||
64636233643365663666656431613966396561366236383363303135613433626466366437396465
|
||||
37303562633336636635363133626238643430663132626331316437626532356237383730626665
|
||||
38373633323531346366313631376231353966626637636262333936343066336639396262646436
|
||||
31616165626466623066336138653966323334326236663439643561663863323130653631643231
|
||||
31396335333066326166383337353033376335376664653162396466346638653531346239353936
|
||||
33663862323135623432333036336162353061363537363463366435643461356562323935653962
|
||||
62333130616466353032316462356233393037326438303064656235323966306535346132663232
|
||||
63393238646534316433643638646536313934666361323061306561396132306431633932313031
|
||||
31356430313463613331363064363265646361353430646563396238326330323038666264653935
|
||||
63306635323439326665306135643730386239356661303232353737383532353363303163313437
|
||||
38623064383035373239623966336563626130636335383833383366343130393939316535333466
|
||||
65353062396632373330663365373761656161653837396666376531376663313466393230646461
|
||||
62306465363166663962316634663763626666306631363731633834366433363630383833393361
|
||||
36393932326138643432666437373463343061313135613163343034373464356666333134366664
|
||||
66343461393733343130636266623661323066623332633930326361626436366237323664336637
|
||||
61316135613330663835353139613039613264383838313337373432623133363735333732376566
|
||||
38633763336438663737653736326466646237313130623934396531306430363461653962336132
|
||||
64313437323766613632376439336234393165646338396334373037323237633737393866303231
|
||||
33646338333532613432393234316235653466633639306465363062656335353034666665623631
|
||||
66386437616462633336636566393537323831313566326637386466616331396464653438396562
|
||||
33343132626463393364386133323163393336313065316433613133663961633033613232343337
|
||||
37313334386533366465353461633930643662326235366139306335656163313864636161623239
|
||||
38336238663630313836363739623334633130616433393536303431333735643565326265613561
|
||||
30613762396162633964336165666137626333643735323330646266666563313935623230643262
|
||||
30383635663035653437333339303730346366333765353739663231643433353764363966353435
|
||||
63663466343864363033646663376261363562636630643038613365333936653165633733623134
|
||||
36626135313330303463336535663235323536613661353332653139336165613261316638666563
|
||||
63346131306536353630363236613864393935333431333864333464353664366134313861633463
|
||||
34336364663030376264663961396235643438653730396661643032623762623965623737326430
|
||||
34333236316335373863663232356136333431666233353138353139313466343762356632396561
|
||||
37356162303636343833316432353831373532326436363538333466333636306666626465666333
|
||||
36653065363538653266643831326234356534303133343564646564323762653238303161336131
|
||||
35396235343837333331396535646564656433343766323765333465356134323536636639623962
|
||||
65633233376136316334653335623666313666376661326362663338633862643963353536616563
|
||||
66323939643332663665306536356566383164356561303935313432373264353738643131653831
|
||||
31346231633037616139373330316231363938386536303432386638323139326132663539663738
|
||||
64636231663538333932363332663137323764346336633336363965616535373030663363363861
|
||||
65363632653831353761306231663562623732353433656637353966303033636666613739306230
|
||||
64363465623031386431663565623966643836383532626134366363656265646563343635383538
|
||||
32346166363832626664613335383731616135376635336266326531663731373633303131373965
|
||||
66663666333739373033616363313132643938656335353164343764383933636265656665663433
|
||||
65386235636531653236333465316331353938323331623733623731303462306566333365383134
|
||||
31356337343732613764633731306335366136346633393265666331636465323566656337323838
|
||||
37393031316630623466393138636666303065623430656336386430363962336539616262633030
|
||||
62616365623765366236303539353166306630393362386430363736313438346266366336323839
|
||||
34376462376633366463636339646337623965633663363862393261373535636230613532386464
|
||||
34393564383130306138366564366666646132363732653036353135656132656339353932383530
|
||||
61636234393165326631303731633062333735306635303566373838393164306538303664313266
|
||||
33346337613836636337316638323631396235643363333836323135303738366235326465376630
|
||||
3363
|
||||
|
||||
2
vars/transcriber.images.yml
Normal file
2
vars/transcriber.images.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
transcriber_image: "transcriber:2fc5a56-1761210134"
|
||||
17
vars/transcriber.yml
Normal file
17
vars/transcriber.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
app_name: "transcriber"
|
||||
app_user: "{{ app_name }}"
|
||||
app_owner_uid: 1017
|
||||
app_owner_gid: 1018
|
||||
base_dir: "{{ (application_dir, app_name) | path_join }}"
|
||||
|
||||
config_dir: "{{ (base_dir, 'config') | path_join }}"
|
||||
config_file: "{{ (config_dir, 'config.toml') | path_join }}"
|
||||
|
||||
data_dir: "{{ (base_dir, 'data') | path_join }}"
|
||||
backups_dir: "{{ (base_dir, 'backups') | path_join }}"
|
||||
|
||||
docker_registry_prefix: "cr.yandex/crplfk0168i4o8kd7ade"
|
||||
|
||||
# Registry images
|
||||
registry_transcriber_image: "{{ (docker_registry_prefix, transcriber_image) | path_join }}"
|
||||
Reference in New Issue
Block a user