Compare commits
4 commits
e932842b8d
...
04bd584e84
Author | SHA1 | Date | |
---|---|---|---|
04bd584e84 | |||
126e3ffd0d | |||
ee97b7acc1 | |||
5b060752fc |
26 changed files with 465 additions and 72 deletions
60
README.md
60
README.md
|
@ -1,14 +1,56 @@
|
|||
## Silicone
|
||||
Un angolo ragionato per facilitare la messa in opera di servizi autogestiti di prossimità
|
||||
### Silicone
|
||||
Un angolo ragionato per facilitare la messa in opera di servizi autogestiti di prossimità.
|
||||
|
||||
#### Come si usa
|
||||
Si imposta il proprio inventory (inventory.yml) e il proprio playbook (infra.yml)
|
||||
Silicone è una raccolta di ruoli [ansible](https://docs.ansible.com/ansible/latest/index.html) fatti a modino e basati su debian stable, un tentativo di fissare alcune scelte tecniche ragionate e poterle ridiscutere in un posto comodo.
|
||||
È molto utile anche per chi vuole tirare su un pad o gancio o altro senza dover necessariamente mettere le mani troppo nella marmellata dei file di configurazione di nginx, ricordarsi di aggiungere il cron per certbot, capire quale versione di nodejs bisogna usare per installare etherpad o trovare un sistema per fare i backup di tutto questo. Qui dentro abbiamo fatto delle scelte.
|
||||
|
||||
|
||||
#### Password
|
||||
Per le password si usa pass, il path usato e' specificato nell'inventory
|
||||
Per usarlo velocemente e conoscendo un minimo ansible, imposta il tuo inventory ([inventory.yml](./inventory.yml)) il tuo playbook ([infra.yml](./infra.yml)) e lancia `ansible-playbook`.
|
||||
|
||||
#### Ansible in breve
|
||||
Ansible è uno strumento a cui si fornisce una lista di macchine da gestire (specificate dentro un file inventory) e si descrive quali ruoli assegnare ad ogni macchina. Ad esempio, diciamo che su ogni server/vm che gestiamo vogliamo installare 3 pacchetti (git, sudo e python3), ecco bisognerà scrivere nel playbook qualcosa come:
|
||||
|
||||
```yaml
|
||||
# test_playbook.yml
|
||||
---
|
||||
- name: Generic servers operation
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: Install generic packages
|
||||
apt:
|
||||
pkg:
|
||||
- sudo
|
||||
- git
|
||||
- python3
|
||||
```
|
||||
|
||||
A questo punto lanciando `./ansible-playbook test_playbook.yml` tutti i server specificati nel file di inventory verranno contattati da ansible via ssh che provvederà ad eseguire le operazioni descritte nel task.
|
||||
|
||||
Un ruolo ansible quindi non è nient'altro che una lista di operazioni.
|
||||
|
||||
#### Password / Keys
|
||||
Per le informazioni sensibili (password del database, dell'account di admin, una chiave ssh) viene usato [passwordstore](https://www.passwordstore.org/), il path usato è specificato nell'inventory con la variabile `passwordstore_path`.
|
||||
|
||||
#### Backup
|
||||
Per i backup usiamo [restic](https://restic.net/).
|
||||
ogni servizio che vuole supportare i backup deve controllare la variabile `with_backup` e specificare di quali database e directory fare i backup (`restic_databases` e `restic_folders`). Le configurazioni sono dentro l'inventory (che le cerca dentro il passwordstore).
|
||||
|
||||
#### Monitoring
|
||||
|
||||
#### Creare nuovi ruoli e testarne di vecchi:
|
||||
Ci sono varie possibilità, si può usare docker o vagrant, sono dentro `dev/`, per Docker c'e' un [README](./dev/README.md)
|
||||
|
||||
|
||||
#### Creare nuovi ruoli:
|
||||
Ci sono varie possibilità, si può usare docker o vagrant, sono dentro
|
||||
`dev/`, per docker c'e' un README.md
|
||||
### Servizi
|
||||
I servizi di alto livello dipendono dai ruoli base, ad esempio etherpad dipende tra gli altri da nodejs, postgresql e opzionalmente anche da nginx e restic. Le dipendenze di un ruolo sono specificate dentro `meta/main.yml` alla voce `dependencies` (vedi le dipendenze del ruolo etherpad come esempio [qui](./roles/stable/etherpad/meta/main.yml))
|
||||
|
||||
<!--
|
||||
#### [Etherpad](https://etherpad.org/)
|
||||
> Un editor di testi collaborativo.
|
||||
=> nginx, certbot, nodejs, restic, etherpad.
|
||||
[Docs](./roles/stable/etherpad/README.md)
|
||||
|
||||
#### [Gancio](https://gancio.org)
|
||||
>
|
||||
|
||||
#### [goploader](https://gpldr.in/) -->
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
# only once
|
||||
docker network create --subnet=172.172.0.0/16 silicone
|
||||
docker build -t silicone:base .
|
||||
### Create a subnet for our test and build the image (debian stable-slim with openssh server and python3 -> ansible dependencies)
|
||||
`docker network create --subnet=172.172.0.0/16 silicone`
|
||||
`docker build -t silicone:base .`
|
||||
|
||||
# for each service to test
|
||||
# create a container with static ip
|
||||
docker run --name etherpad -d --net silicone --ip 172.172.0.2 -it silicone:base
|
||||
### Create a container with static ip for each service to test (e.g. __etherpad__ here)
|
||||
`docker run --name etherpad -d --net silicone --ip 172.172.0.2 -it silicone:base`
|
||||
|
||||
# copy your ssh key
|
||||
docker cp ~/.ssh/id_rsa.pub etherpad:/root/.ssh/authorized_keys
|
||||
docker exec -it etherpad chown root.root /root/.ssh/authorized_keys
|
||||
### Copy your ssh key
|
||||
`docker cp ~/.ssh/id_rsa.pub etherpad:/root/.ssh/authorized_keys`
|
||||
`docker exec -it etherpad chown root.root /root/.ssh/authorized_keys`
|
||||
|
||||
|
||||
# then you can go with ansible using 172.172.0.2 as your host inside
|
||||
inventory
|
||||
### Then you can go with ansible using 172.172.0.2 as your host inside inventory.
|
||||
|
|
|
@ -31,6 +31,6 @@
|
|||
# TEST
|
||||
- name: Test
|
||||
hosts: test
|
||||
roles: ['stable/common', 'stable/nginx']
|
||||
roles: ['stable/common', 'stable/etherpad']
|
||||
tags: test
|
||||
vars_files: vars/frontend.yml
|
||||
vars_files: vars/test.yml
|
||||
|
|
|
@ -18,3 +18,10 @@ test:
|
|||
all:
|
||||
vars:
|
||||
passwordstore_path: cisti.org/ansible
|
||||
restic_default_folders: []
|
||||
restic_password: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/restic/{{{{ansible_hostname}}_pwd create=True nosymbols=true')}}"
|
||||
restic_repository_name: "{{ansible_hostname}}"
|
||||
restic_ssh_private_key: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/restic/ssh_private returnall=true')}}"
|
||||
restic_ssh_hostname: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/restic/ssh_hostname')}}"
|
||||
restic_ssh_user: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/restic/ssh_user')}}"
|
||||
restic_ssh_port: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/restic/ssh_port')}}"
|
|
@ -4,8 +4,8 @@ favicon: "favicon.ico"
|
|||
listen_ip: "0.0.0.0"
|
||||
listen_port: "8001"
|
||||
log_level: "INFO"
|
||||
database_password: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/etherpad/db_password create=True nosymbols=true')}}"
|
||||
pad_admin_password: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/etherpad/admin_password create=True nosymbols=true')}}"
|
||||
database_password: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/etherpad_{{ansible_hostname}}/db_password create=True nosymbols=true')}}"
|
||||
pad_admin_password: "{{lookup('community.general.passwordstore', '{{passwordstore_path}}/etherpad_{{ansible_hostname}}/admin_password create=True nosymbols=true')}}"
|
||||
|
||||
plugins: ['ep_headings2', 'ep_table_of_contents', 'ep_comments_page', 'ep_align', 'ep_delete_after_delay_lite']
|
||||
|
||||
|
@ -15,4 +15,3 @@ pad_default_text: |
|
|||
Welcome to Etherpad!
|
||||
This pad text is synchronized as you type, so that everyone viewing this page sees the same text.
|
||||
This allows you to collaborate seamlessly on documents!
|
||||
Get involved with Etherpad at
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
- name: restart etherpad
|
||||
service:
|
||||
name: etherpad
|
||||
state: restarted
|
|
@ -13,8 +13,15 @@ dependencies:
|
|||
database: etherpad
|
||||
|
||||
# install certbot nginx and configure it as reverse proxy
|
||||
# - role: stable/nginx
|
||||
# when: with_nginx | bool
|
||||
# vars:
|
||||
# with_certbot: true
|
||||
# proxy_pass: http://
|
||||
- role: stable/nginx
|
||||
when: with_nginx | bool
|
||||
vars:
|
||||
with_certbot: true
|
||||
proxy_pass: http://localhost:8001
|
||||
|
||||
# backup etherpad database
|
||||
- role: stable/restic
|
||||
when: with_backup | bool
|
||||
vars:
|
||||
restic_databases:
|
||||
- {name: 'etherpad', dump_command: sudo -Hiu postgres pg_dump -Fc etherpad}
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
|
||||
- name: install etherpad deps
|
||||
become: yes
|
||||
apt:
|
||||
pkg:
|
||||
- git
|
||||
|
@ -8,6 +9,7 @@
|
|||
- tidy
|
||||
|
||||
- name: ensure etherpad user is present
|
||||
become: yes
|
||||
user:
|
||||
name: "etherpad"
|
||||
home: "/srv/etherpad"
|
||||
|
@ -18,13 +20,14 @@
|
|||
git:
|
||||
repo: "https://github.com/ether/etherpad-lite"
|
||||
dest: "/srv/etherpad/etherpad"
|
||||
version: "1.8.6"
|
||||
version: "1.8.7"
|
||||
force: true
|
||||
become: true
|
||||
become_user: "etherpad"
|
||||
register: repository
|
||||
|
||||
- name: ensure etherpad init.d is latest
|
||||
become: yes
|
||||
template:
|
||||
src: etherpad.initd.j2
|
||||
dest: /etc/init.d/etherpad
|
||||
|
@ -33,6 +36,7 @@
|
|||
mode: 0500
|
||||
|
||||
- name: copy etherpad settings.json
|
||||
become: yes
|
||||
template:
|
||||
src: settings.json.j2
|
||||
dest: /srv/etherpad/etherpad/settings.json
|
||||
|
@ -41,6 +45,7 @@
|
|||
mode: 0644
|
||||
|
||||
- name: ensure etherpad will start after system is booted
|
||||
become: yes
|
||||
service:
|
||||
name: etherpad
|
||||
enabled: yes
|
||||
|
@ -53,19 +58,20 @@
|
|||
# chdir: /srv/etherpad/etherpad/
|
||||
|
||||
- name: copy custom assets
|
||||
become: yes
|
||||
copy:
|
||||
src: "{{playbook_dir}}/assets/etherpad/{{item.key}}"
|
||||
dest: "{{item.value}}{{item.key}}"
|
||||
owner: etherpad
|
||||
group: etherpad
|
||||
with_dict: "{{ override_files }}"
|
||||
with_dict: "{{ override_files| default([]) }}"
|
||||
|
||||
- name: remove package-lock.json
|
||||
become: yes
|
||||
file:
|
||||
state: absent
|
||||
path: "/srv/etherpad/etherpad/package-lock.json"
|
||||
|
||||
|
||||
- name: install etherpad plugins
|
||||
npm:
|
||||
name: "{{ item }}"
|
||||
|
@ -73,4 +79,9 @@
|
|||
become: true
|
||||
become_user: etherpad
|
||||
with_items: "{{ plugins|d() }}"
|
||||
notify: restart etherpad
|
||||
|
||||
- name: restart etherpad
|
||||
become: true
|
||||
service:
|
||||
name: etherpad
|
||||
state: restarted
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
- name: Install postgresql
|
||||
apt:
|
||||
pkg:
|
||||
- postgresql
|
||||
- python3-psycopg2
|
||||
|
||||
- name: Create etherpad postgresql db
|
||||
become: yes
|
||||
become_user: postgres
|
||||
postgresql_db:
|
||||
name: etherpad
|
||||
|
||||
- name: Create etherpad postgresql user
|
||||
become: yes
|
||||
become_user: postgres
|
||||
postgresql_user:
|
||||
db: etherpad
|
||||
name: etherpad
|
||||
password: etherpad
|
||||
|
||||
|
|
@ -9,8 +9,6 @@ server {
|
|||
|
||||
location / {
|
||||
proxy_pass {{item.proxy_pass}};
|
||||
proxy_http_version 1.1;
|
||||
|
||||
|
||||
# set host
|
||||
proxy_set_header Host $host;
|
||||
|
@ -19,10 +17,17 @@ server {
|
|||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# upgrade websocket
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
# websocket proxy
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# compression
|
||||
gzip on;
|
||||
gzip_types text/plain application/xml application/json;
|
||||
gzip_proxied no-cache no-store private expired auth;
|
||||
gzip_min_length 1000;
|
||||
|
||||
# cache
|
||||
proxy_cache STATIC;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
when: nodejs_install_npm_user is not defined
|
||||
|
||||
- name: Create npm global directory
|
||||
become: yes
|
||||
file:
|
||||
path: "{{ npm_config_prefix }}"
|
||||
owner: "{{ nodejs_install_npm_user }}"
|
||||
|
@ -14,12 +15,14 @@
|
|||
state: directory
|
||||
|
||||
- name: Add npm_config_prefix bin directory to global $PATH.
|
||||
become: yes
|
||||
template:
|
||||
src: npm.sh.j2
|
||||
dest: /etc/profile.d/npm.sh
|
||||
mode: 0644
|
||||
|
||||
- name: Ensure npm global packages are installed.
|
||||
become: yes
|
||||
npm:
|
||||
name: "{{ item.name | default(item) }}"
|
||||
version: "{{ item.version | default('latest') }}"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
- name: Ensure dependencies are present.
|
||||
become: yes
|
||||
apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
|
@ -8,12 +9,14 @@
|
|||
state: present
|
||||
|
||||
- name: Add Nodesource apt key.
|
||||
become: yes
|
||||
apt_key:
|
||||
url: https://keyserver.ubuntu.com/pks/lookup?op=get&fingerprint=on&search=0x1655A0AB68576280
|
||||
id: "68576280"
|
||||
state: present
|
||||
|
||||
- name: Add NodeSource repositories for Node.js.
|
||||
become: yes
|
||||
apt_repository:
|
||||
repo: "{{ item }}"
|
||||
state: present
|
||||
|
@ -23,11 +26,15 @@
|
|||
register: node_repo
|
||||
|
||||
- name: Update apt cache if repo was added.
|
||||
apt: update_cache=yes
|
||||
become: yes
|
||||
apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 43200 # 12 hours
|
||||
when: node_repo.changed
|
||||
tags: ['skip_ansible_lint']
|
||||
|
||||
- name: Ensure Node.js and npm are installed.
|
||||
become: yes
|
||||
apt:
|
||||
name: "nodejs={{ nodejs_version|regex_replace('x', '') }}*"
|
||||
state: present
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
- name: Install postgresql
|
||||
become: yes
|
||||
apt:
|
||||
pkg:
|
||||
- acl
|
||||
|
|
125
roles/stable/restic/README.md
Normal file
125
roles/stable/restic/README.md
Normal file
|
@ -0,0 +1,125 @@
|
|||
# Ansible role for Restic
|
||||
|
||||
This role will setup [Restic](https://restic.net/) backups on a Debian/Ubuntu machine using a systemd service and timer.
|
||||
|
||||
It supports S3 backend or SFTP backend and will thus setup the SSH config and SSH private keys (see variables below).
|
||||
|
||||
## Role Variables
|
||||
|
||||
### Restic installation
|
||||
|
||||
The role will download and install the restic binary (version `restic_version`) into `restic_path` if the file does not exist.
|
||||
|
||||
If you want to force the installation, overwrite the binary or update restic, you can run ansible with `--extra-vars restic_install=true`.
|
||||
|
||||
### Restic configuration
|
||||
|
||||
- `restic_user`: user to run restic as (`root`)
|
||||
- `restic_user_home`: home directory of the restic_user (`/root`)
|
||||
- `restic_password`: password used for repository encryption
|
||||
- `restic_repository_name`: the name of the repository (`restic`)
|
||||
- `restic_check`: run `restic check` as `ExecStartPre` if true (`false`)
|
||||
- `restic_default_folders`: a default list of folders that restic will backup (`/etc/`, `/root` and `/var/log`)
|
||||
- `restic_folders`: the list of folder you want to backup
|
||||
- `restic_dump_compression_enabled`: enable piping to pigz for database dumps
|
||||
|
||||
Each folder has a `path` and an `exclude` property (which defaults to nothing). The `exclude` property is the literal argument passed to restic (exemple: `--exclude .cache --exclude .local`).
|
||||
|
||||
`restic_default_folders` and `restic_folders` are combined to form the final list of backuped folders.
|
||||
|
||||
- `restic_databases`: a list of databases to dump
|
||||
|
||||
Each database has a `name` property which will be the name of the restic snapshot (`{{ database.name }}.sql`). They also have a `dump_command` property which is the command to dump the database to stdout (like `mysqldump dbname`).
|
||||
|
||||
- `restic_forget`: run `restic forget` as `ExecStartPost` with `--keep-within {{ restic_forget_keep_within }}` (`true`)
|
||||
- `restic_forget_keep_within`: period of time to use with `--keep-within` (`30d`)
|
||||
- `restic_prune`: run `restic prune` as `ExecStartPost` (`true`)
|
||||
|
||||
### SSH/SFTP backend configuration
|
||||
|
||||
The SSH configuration will be written in `{{ restic_user_home }}/.ssh/config`.
|
||||
|
||||
- `restic_ssh_host`: backend name and SSH alias for the backup host
|
||||
- `restic_ssh_user`: user for SSH connection
|
||||
- `restic_ssh_hostname`: actual SSH hostname of the backup machine
|
||||
- `restic_ssh_private_key`: private SSH key used to connect to the backup host
|
||||
- `restic_ssh_private_key_path`: path of the private key to use (`~/.ssh/backup`)
|
||||
- `restic_ssh_port`: SSH port to use with the backup machine (`23`)
|
||||
|
||||
### S3 backend configuration
|
||||
|
||||
- `restic_ssh_enabled`: set to false
|
||||
- `restic_repository_name`: set to s3 endpoint + bucket, restic syntax (e.g. `s3:https://s3.fr-par.scw.cloud/restic-bucket`)
|
||||
- `restic_aws_access_key_id`: `AWS_ACCESS_KEY_ID`
|
||||
- `restic_aws_secret_access_key`: `AWS_SECRET_ACCESS_KEY`
|
||||
|
||||
### Sytemd service and timer
|
||||
|
||||
A `restic-backup.service` service will be created with all the parameters defined above. The service is of type `oneshot` and will be triggered periodically with `restic-backup.timer`.
|
||||
|
||||
The timer is configurable as follows:
|
||||
|
||||
- `restic_systemd_timer_on_calender`: defines the `OnCalendar` directive (`*-*-* 03:00:00`)
|
||||
- `restic_systemd_timer_randomized_delay_sec`: Delay the timer by a random amount of time between 0 and the specified time value. (`0`)
|
||||
|
||||
See the [systemd.timer](https://www.freedesktop.org/software/systemd/man/systemd.timer.html) documentation for more information.
|
||||
|
||||
You can see the logs of the backup with `journalctl`. (`journalctl -xefu restic-backup`).
|
||||
|
||||
## Example playbook
|
||||
|
||||
```yaml
|
||||
---
|
||||
|
||||
- hosts: myhost
|
||||
roles: restic
|
||||
vars:
|
||||
restic_ssh_user: backupuser
|
||||
restic_ssh_hostname: storage-server.infra.tld
|
||||
restic_folders:
|
||||
- {path: "/srv"}
|
||||
- {path: "/var/www"}
|
||||
restic_databases:
|
||||
- {name: website, dump_command: sudo -Hiu postgres pg_dump -Fc website}
|
||||
- {name: website2, dump_command: mysqldump website2}
|
||||
restic_password: mysuperduperpassword
|
||||
restic_ssh_private_key: |-
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACAocs5g1I4kFQ1HH/YZiVU+zLhRDu4tfzZ9CmFAfKhL2AAAAJi02XEwtNlx
|
||||
MAAAAAtzc2gtZWQyNTUxOQAAACAocs5g1I4kFQ1HH/YZiVU+zLhRDu4tfzZ9CmFAfKhL2A
|
||||
AAAEADZf2Pv4G74x+iNtuwSV/ItnR3YQJ/KUaNTH19umA/tChyzmDUjiQVDUcf9hmJVT7M
|
||||
uFEO7i1/Nn0KYUB8qEvYAAAAE3N0YW5pc2xhc0BtYnAubG9jYWwBAg==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
```
|
||||
|
||||
S3 example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
|
||||
- hosts: myhost
|
||||
roles: restic
|
||||
vars:
|
||||
restic_ssh_enabled: false
|
||||
restic_repository: "s3:https://s3.fr-par.scw.cloud/restic-bucket"
|
||||
restic_aws_access_key_id: xxxxx
|
||||
restic_aws_secret_access_key: xxxxx
|
||||
restic_folders:
|
||||
- {path: "/srv"}
|
||||
- {path: "/var/www"}
|
||||
restic_databases:
|
||||
- {name: website, dump_command: sudo -Hiu postgres pg_dump -Fc website}
|
||||
- {name: website2, dump_command: mysqldump website2}
|
||||
restic_password: mysuperduperpassword
|
||||
```
|
||||
|
||||
Of course, `restic_password` and `restic_ssh_private_key` should be stored using ansible-vault.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Author Information
|
||||
|
||||
See my other Ansible roles at [angristan/ansible-roles](https://github.com/angristan/ansible-roles).
|
24
roles/stable/restic/defaults/main.yml
Normal file
24
roles/stable/restic/defaults/main.yml
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
restic_install: false
|
||||
restic_version: 0.11.0
|
||||
restic_path: /usr/local/bin/restic
|
||||
restic_user: root
|
||||
restic_user_home: /root
|
||||
|
||||
restic_repository_name: restic
|
||||
restic_default_folders: []
|
||||
restic_folders: []
|
||||
restic_databases: []
|
||||
restic_dump_compression_enabled: true
|
||||
restic_forget: true
|
||||
restic_forget_keep_within: 30d
|
||||
restic_prune: true
|
||||
restic_check: true
|
||||
|
||||
restic_ssh_enabled: true
|
||||
restic_ssh_host: backup
|
||||
restic_ssh_port: 22
|
||||
restic_ssh_private_key_path: '/root/.ssh/backup'
|
||||
|
||||
restic_systemd_timer_on_calender: '*-*-* 03:00:00'
|
||||
restic_systemd_timer_randomized_delay_sec: 1000
|
6
roles/stable/restic/handlers/main.yml
Normal file
6
roles/stable/restic/handlers/main.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
|
||||
- name: systemd reload
|
||||
become: yes
|
||||
systemd:
|
||||
daemon_reload: yes
|
42
roles/stable/restic/tasks/install.yml
Normal file
42
roles/stable/restic/tasks/install.yml
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
|
||||
- name: Install fuse (to mount repositories)
|
||||
become: yes
|
||||
apt:
|
||||
name: fuse
|
||||
|
||||
- name: Install bzip2 (to install restic)
|
||||
become: yes
|
||||
apt:
|
||||
name: bzip2
|
||||
|
||||
- name: Install pigz (to compress db dumps)
|
||||
become: yes
|
||||
apt:
|
||||
name: pigz
|
||||
|
||||
- name: Download restic
|
||||
become: yes
|
||||
get_url:
|
||||
url: 'https://github.com/restic/restic/releases/download/v{{ restic_version }}/restic_{{ restic_version }}_linux_amd64.bz2'
|
||||
dest: '/tmp/restic_{{ restic_version }}_linux_amd64.bz2'
|
||||
|
||||
- name: Extract restic
|
||||
become: yes
|
||||
command: 'bzip2 -d /tmp/restic_{{ restic_version }}_linux_amd64.bz2'
|
||||
args:
|
||||
creates: '/tmp/restic_{{ restic_version }}_linux_amd64'
|
||||
|
||||
- name: Install restic
|
||||
become: yes
|
||||
copy:
|
||||
remote_src: true
|
||||
src: '/tmp/restic_{{ restic_version }}_linux_amd64'
|
||||
dest: "{{ restic_path }}"
|
||||
mode: 0755
|
||||
|
||||
- name: Remove downloaded file
|
||||
become: yes
|
||||
file:
|
||||
path: '/tmp/restic_{{ restic_version }}_linux_amd64'
|
||||
state: absent
|
67
roles/stable/restic/tasks/main.yml
Normal file
67
roles/stable/restic/tasks/main.yml
Normal file
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
- name: Check if restic is installed
|
||||
stat:
|
||||
path: '{{ restic_path }}'
|
||||
register: restic_binary
|
||||
|
||||
- include_tasks: install.yml
|
||||
when: not restic_binary.stat.exists or restic_install
|
||||
|
||||
- name: Overwrite SSH config for backup server
|
||||
become: yes
|
||||
template:
|
||||
src: ssh_config.j2
|
||||
dest: '{{ restic_user_home }}/.ssh/config'
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0600'
|
||||
when: restic_ssh_enabled
|
||||
|
||||
- name: Add SSH private key
|
||||
become: yes
|
||||
template:
|
||||
src: ssh_private_key.j2
|
||||
dest: '{{ restic_ssh_private_key_path }}'
|
||||
mode: '0600'
|
||||
when: restic_ssh_private_key is defined and restic_ssh_enabled
|
||||
|
||||
- name: Add restic_env in home folder
|
||||
become: yes
|
||||
template:
|
||||
src: restic_env.j2
|
||||
dest: '{{ restic_user_home }}/.restic_env'
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0600'
|
||||
|
||||
- name: Add systemd service for restic
|
||||
become: yes
|
||||
template:
|
||||
src: restic-backup.service.j2
|
||||
dest: /etc/systemd/system/restic-backup.service
|
||||
mode: '0644'
|
||||
vars:
|
||||
restic_folders_combined: '{{ restic_default_folders + restic_folders }}'
|
||||
notify: systemd reload
|
||||
|
||||
- name: Add systemd timer for restic
|
||||
become: yes
|
||||
template:
|
||||
src: restic-backup.timer.j2
|
||||
dest: /etc/systemd/system/restic-backup.timer
|
||||
mode: '0644'
|
||||
notify: systemd reload
|
||||
|
||||
- name: Enable and start restic timer
|
||||
become: yes
|
||||
systemd:
|
||||
name: restic-backup.timer
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Initialize restic repo if needed
|
||||
become: yes
|
||||
command: "{{restic_path}} init"
|
||||
environment:
|
||||
RESTIC_REPOSITORY: "sftp:{{ restic_ssh_host }}:{{ restic_repository_name }}"
|
||||
RESTIC_PASSWORD: "{{restic_password}}"
|
40
roles/stable/restic/templates/restic-backup.service.j2
Normal file
40
roles/stable/restic/templates/restic-backup.service.j2
Normal file
|
@ -0,0 +1,40 @@
|
|||
[Unit]
|
||||
Description=Restic backup
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User={{ restic_user }}
|
||||
|
||||
CPUQuota={{ 25 * ansible_processor_vcpus }}%
|
||||
|
||||
{% if restic_ssh_enabled %}
|
||||
Environment="RESTIC_REPOSITORY=sftp:{{ restic_ssh_host }}:{{ restic_repository_name }}"
|
||||
{% else %}
|
||||
Environment="RESTIC_REPOSITORY={{ restic_repository }}"
|
||||
{% endif -%}
|
||||
Environment="RESTIC_PASSWORD={{ restic_password}}"
|
||||
|
||||
{% if restic_aws_access_key_id is defined and restic_aws_secret_access_key is defined %}
|
||||
Environment="AWS_ACCESS_KEY_ID={{ restic_aws_access_key_id}}"
|
||||
Environment="AWS_SECRET_ACCESS_KEY={{ restic_aws_secret_access_key}}"
|
||||
{% endif %}
|
||||
|
||||
{% if restic_check %}
|
||||
ExecStartPre={{ restic_path }} check
|
||||
{% endif -%}
|
||||
|
||||
{% for folder in restic_folders_combined %}
|
||||
ExecStart={{ restic_path }} backup --verbose {{ folder.path }} {{ folder.exclude if folder.exclude is defined else '' }}
|
||||
{% endfor -%}
|
||||
|
||||
{% for database in restic_databases %}
|
||||
ExecStart=/bin/sh -c "{{ database.dump_command }} {{ '| pigz |' if restic_dump_compression_enabled else '|' }} {{ restic_path }} backup --verbose --stdin --stdin-filename {{ database.name }}{{ '.sql.gz' if restic_dump_compression_enabled else '.sql' }}"
|
||||
{% endfor -%}
|
||||
|
||||
{% if restic_forget %}
|
||||
ExecStartPost={{ restic_path }} forget --keep-within {{ restic_forget_keep_within }}
|
||||
{% endif -%}
|
||||
|
||||
{% if restic_prune %}
|
||||
ExecStartPost={{ restic_path }} prune
|
||||
{% endif -%}
|
9
roles/stable/restic/templates/restic-backup.timer.j2
Normal file
9
roles/stable/restic/templates/restic-backup.timer.j2
Normal file
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=Restic backup
|
||||
|
||||
[Timer]
|
||||
OnCalendar={{ restic_systemd_timer_on_calender }}
|
||||
RandomizedDelaySec={{ restic_systemd_timer_randomized_delay_sec }}
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
11
roles/stable/restic/templates/restic_env.j2
Normal file
11
roles/stable/restic/templates/restic_env.j2
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% if restic_ssh_enabled %}
|
||||
export RESTIC_REPOSITORY=sftp:{{ restic_ssh_host }}:{{ restic_repository_name }}
|
||||
{% else %}
|
||||
export RESTIC_REPOSITORY="{{ restic_repository }}"
|
||||
{% endif -%}
|
||||
export RESTIC_PASSWORD={{ restic_password}}
|
||||
|
||||
{% if restic_aws_access_key_id is defined and restic_aws_secret_access_key is defined %}
|
||||
export AWS_ACCESS_KEY_ID={{ restic_aws_access_key_id}}
|
||||
export AWS_SECRET_ACCESS_KEY={{ restic_aws_secret_access_key}}
|
||||
{% endif %}
|
5
roles/stable/restic/templates/ssh_config.j2
Normal file
5
roles/stable/restic/templates/ssh_config.j2
Normal file
|
@ -0,0 +1,5 @@
|
|||
Host {{ restic_ssh_host }}
|
||||
User {{ restic_ssh_user }}
|
||||
HostName {{ restic_ssh_hostname }}
|
||||
IdentityFile {{ restic_ssh_private_key_path }}
|
||||
Port {{ restic_ssh_port }}
|
1
roles/stable/restic/templates/ssh_private_key.j2
Normal file
1
roles/stable/restic/templates/ssh_private_key.j2
Normal file
|
@ -0,0 +1 @@
|
|||
{{ restic_ssh_private_key }}
|
|
@ -2,15 +2,15 @@
|
|||
title: "Pad@cisti"
|
||||
pad_lang: "it-IT"
|
||||
pad_default_text: |
|
||||
Sei su pad.cisti.org! Qui potrai usare usare PAD.
|
||||
Un PAD è uno strumento di scrittura collaborativa per scrivere testi, comunicati o quello che vuoi assieme ad altre persone!
|
||||
Sei sul pad di cisti.org!
|
||||
Un PAD è uno strumento di scrittura collaborativa per scrivere testi, comunicati o quello che vuoi assieme ad altre persone.
|
||||
Questo è uno dei servizi di cisti.org, fuori dalle logiche del profitto e del capitalismo, dietro ci sono un gruppo di persone volontarie che si responsabilizzano a mantenere in piedi tutto questo.
|
||||
|
||||
ALCUNE COSE DA SAPERE:
|
||||
- Per iniziare cancella tutto questo testo e inizia a scrivere!
|
||||
- Ogni pad può essere modificato da CHIUNQUE sia in possesso del sito (URL) o che possa indovinarlo facilmente, quindi scegli bene il nome del pad che vuoi creare!
|
||||
- Questo pad verrà eliminato automaticamente dopo 60 giorni di inattività
|
||||
- Una volta cancellato un pad NON ci sono modi di recuperarlo!
|
||||
- Questo pad verrà eliminato automaticamente dopo 60 giorni di inattività.
|
||||
- Una volta cancellato un pad NON ci sono modi di recuperarlo.
|
||||
- Questo pad ci tiene così tanto alla privacy che non sappiamo neanche chi sei, rispetta l'anonimato e usalo bene.
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ certbot_email: info@cisti.org
|
|||
servers:
|
||||
- cicles:
|
||||
server_name: antani.cisti.org
|
||||
proxy_pass: http://192.168.199.105:8080
|
||||
proxy_pass: http://localhost:8001
|
||||
custom_config: |
|
||||
sendfile on;
|
||||
client_max_body_size 500m;
|
||||
|
|
10
vars/test.yml
Normal file
10
vars/test.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
with_certbot: true
|
||||
with_nginx: true
|
||||
with_backup: true
|
||||
certbot_email: info@cisti.org
|
||||
servers:
|
||||
- cicles:
|
||||
server_name: antani.cisti.org
|
||||
proxy_pass: http://localhost:8001
|
||||
|
Loading…
Reference in a new issue