Implement roles: pureftpd_doorbell, rsync.mycloud

pureftpd_doorbell (ftp_servers/acemagic):
- instaluje pure-ftpd, konfiguruje chroot, passive ports, brak anonimowych
- tworzy uzytkownika hikvision z haslem z vault
- uruchamia pure-ftpd-wrapper (Debian service name)

rsync.mycloud (mycloud):
- deployuje skrypt rsync_to_asustor.sh na MyCloud EX2 Ultra
- rsync /shares/ -> asustor:8883 /volume1/mycloud-backup/ co noc o 02:00
- lockfile zapobiega rownoleglem uruchomieniu
- cron job na MyCloud
This commit is contained in:
blasebast 2026-04-11 00:15:51 +02:00
parent 9845d7985d
commit 397c909c14
8 changed files with 181 additions and 4 deletions

View File

@ -1,5 +1,6 @@
---
- hosts: ftp_servers
- name: Configure pureFTPd for Hikvision doorbell
hosts: ftp_servers
become: true
roles:
- ../roles/pureftpd_doorbell
- pureftpd_doorbell

View File

@ -1,4 +1,6 @@
---
- hosts: mycloud
- name: Deploy rsync script on MyCloud
hosts: mycloud
become: true
roles:
- ../roles/rsync.mycloud
- rsync.mycloud

View File

@ -0,0 +1,12 @@
---
# Uzytkownik FTP dla kamery/dzwonka Hikvision
ftp_doorbell_user: "hikvision"
ftp_doorbell_root: "/media/seagata16t/hikvision16t/ftp_hik4"
ftp_doorbell_port: 21
# Zakres pasywnych portow FTP
ftp_passive_port_min: 30000
ftp_passive_port_max: 30100
# Haslo z vault (ftp_password_secret musi byc zdefiniowane w inventory/host_vars lub vault)
# ftp_password_secret: "z_vault"

View File

@ -0,0 +1,6 @@
---
- name: restart pure-ftpd
systemd:
name: pure-ftpd-wrapper
state: restarted
when: not ansible_check_mode

View File

@ -0,0 +1,72 @@
---
- name: Load vault vars
include_vars: "{{ playbook_dir }}/../roles/common/vars/vault.yml"
- name: Zainstaluj pure-ftpd i narzedzia
apt:
name:
- pure-ftpd
- pure-ftpd-common
- python3-passlib
state: present
update_cache: yes
- name: Upewnij sie ze katalog FTP istnieje
file:
path: "{{ ftp_doorbell_root }}"
state: directory
owner: "{{ ftp_doorbell_user }}"
group: "{{ ftp_doorbell_user }}"
mode: '0755'
- name: Upewnij sie ze uzytkownik systemowy istnieje (nologin)
user:
name: "{{ ftp_doorbell_user }}"
shell: /usr/sbin/nologin
home: "{{ ftp_doorbell_root }}"
create_home: no
system: yes
- name: Skonfiguruj pure-ftpd - tryb standalone
copy:
dest: /etc/pure-ftpd/conf/Daemonize
content: "yes\n"
notify: restart pure-ftpd
- name: Skonfiguruj pure-ftpd - chroot
copy:
dest: /etc/pure-ftpd/conf/ChrootEveryone
content: "yes\n"
notify: restart pure-ftpd
- name: Skonfiguruj pure-ftpd - pasywne porty
copy:
dest: /etc/pure-ftpd/conf/PassivePortRange
content: "{{ ftp_passive_port_min }} {{ ftp_passive_port_max }}\n"
notify: restart pure-ftpd
- name: Skonfiguruj pure-ftpd - zakaz anonimowych
copy:
dest: /etc/pure-ftpd/conf/NoAnonymous
content: "yes\n"
notify: restart pure-ftpd
- name: Skonfiguruj pure-ftpd - port
lineinfile:
path: /etc/pure-ftpd/conf/Bind
line: "0.0.0.0 {{ ftp_doorbell_port }}"
create: yes
notify: restart pure-ftpd
- name: Ustaw haslo uzytkownika FTP
user:
name: "{{ ftp_doorbell_user }}"
password: "{{ ftp_password_secret | password_hash('sha512') }}"
- name: Uruchom i wlacz pure-ftpd
systemd:
name: pure-ftpd-wrapper
state: started
enabled: yes
daemon_reload: yes
when: not ansible_check_mode

View File

@ -0,0 +1,17 @@
---
# Zrodlo danych na MyCloud EX2 Ultra
rsync_mycloud_source: "/shares/"
# Cel - Asustor przez SSH (montowany przez autofs na acemagic jako /media/asustor)
rsync_mycloud_dest_host: "192.168.1.10"
rsync_mycloud_dest_port: 8883
rsync_mycloud_dest_user: "admin"
rsync_mycloud_dest_path: "/volume1/mycloud-backup/"
# Gdzie deployowac skrypt na MyCloud
rsync_mycloud_script_path: "/usr/local/bin/rsync_to_asustor.sh"
rsync_mycloud_log_path: "/var/log/rsync_mycloud.log"
# Cron - domyslnie co noc o 02:00
rsync_mycloud_cron_hour: "2"
rsync_mycloud_cron_minute: "0"

View File

@ -0,0 +1,37 @@
---
- name: Sprawdz czy rsync jest dostepny
command: which rsync
register: rsync_check
changed_when: false
failed_when: false
- name: Ostrzez jesli rsync nie istnieje
debug:
msg: "UWAGA: rsync nie znaleziony na MyCloud - zainstaluj recznie lub przez WD UI"
when: rsync_check.rc != 0
- name: Deploy skryptu rsync
template:
src: rsync_to_asustor.sh.j2
dest: "{{ rsync_mycloud_script_path }}"
mode: '0755'
owner: root
group: root
- name: Upewnij sie ze plik logu istnieje
file:
path: "{{ rsync_mycloud_log_path }}"
state: touch
owner: root
group: root
mode: '0644'
changed_when: false
- name: Cron - rsync MyCloud do Asustor
cron:
name: "rsync MyCloud to Asustor"
hour: "{{ rsync_mycloud_cron_hour }}"
minute: "{{ rsync_mycloud_cron_minute }}"
job: "{{ rsync_mycloud_script_path }} >> {{ rsync_mycloud_log_path }} 2>&1"
user: root
state: present

View File

@ -0,0 +1,30 @@
#!/bin/sh
# rsync MyCloud -> Asustor - Managed by Ansible
LOGFILE="{{ rsync_mycloud_log_path }}"
LOCKFILE="/var/run/rsync_mycloud.lock"
# Blokada przed rownoleglym uruchomieniem
if [ -f "$LOCKFILE" ]; then
echo "$(date): SKIPPED - already running (lockfile exists)" >> "$LOGFILE"
exit 0
fi
touch "$LOCKFILE"
trap "rm -f $LOCKFILE" EXIT
echo "$(date): Starting rsync MyCloud -> Asustor" >> "$LOGFILE"
rsync -avz --delete \
-e "ssh -p {{ rsync_mycloud_dest_port }} -o StrictHostKeyChecking=no -o ConnectTimeout=10" \
"{{ rsync_mycloud_source }}" \
"{{ rsync_mycloud_dest_user }}@{{ rsync_mycloud_dest_host }}:{{ rsync_mycloud_dest_path }}" \
>> "$LOGFILE" 2>&1
RC=$?
if [ $RC -eq 0 ]; then
echo "$(date): rsync SUCCESS" >> "$LOGFILE"
else
echo "$(date): rsync FAILED (rc=$RC)" >> "$LOGFILE"
fi
exit $RC