Compare commits

...

2 Commits

Author SHA1 Message Date
Clément Désiles 25621a101c Merge branch 'main' of github.com:cdesiles/ansible-playbooks 2026-06-12 22:34:24 +02:00
Clément Désiles 0726e417d2 feat: add syncthing support 2026-06-03 23:28:26 +02:00
5 changed files with 182 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
# syncthing
Installs and configures [Syncthing](https://syncthing.net/) as a system service.
Runs as a dedicated `syncthing` system user via `syncthing@syncthing.service`.
Supports Arch Linux and Debian-based distributions.
## Required variables
Set these in `inventory/host_vars/<host>.yml`:
```yaml
syncthing_gui_user: admin
syncthing_gui_password: "{{ vault_syncthing_gui_password }}"
```
`syncthing_gui_password` must be at least 12 characters. Set the actual value
in your vault file and reference it via `vault_syncthing_gui_password`.
Syncthing will bcrypt-hash the password on first start.
## Optional variables
See `defaults/main.yml` for the full list. Key options:
| Variable | Default | Description |
|-----------------------------|--------------------------------|------------------------------------|
| `syncthing_user` | `syncthing` | OS user to run syncthing as |
| `syncthing_home` | `/var/lib/syncthing` | Home directory for the system user |
| `syncthing_config_dir` | `{{ syncthing_home }}/.config/syncthing` | Config directory |
| `syncthing_gui_bind` | `0.0.0.0` | GUI listen address |
| `syncthing_gui_port` | `8384` | GUI listen port |
| `syncthing_port` | `22000` | Sync protocol port (TCP) |
| `syncthing_allowed_networks` | `[]` | UFW rules for GUI and sync ports |
## Notes
- `config.xml` is written only on first run — the task is skipped on subsequent
runs if the file already exists. Syncthing manages the file after that (device
ID, folder config, hashed password). Re-running the playbook is safe.
- Folder and device pairing must be done via the Syncthing web UI or REST API
after the service is running.
- The GUI binds to `0.0.0.0` by default — use `syncthing_allowed_networks` to
restrict access via UFW to specific LAN/VPN ranges.
## Debian notes
The `syncthing` package in some Debian versions may be outdated. Consider adding
the [official APT repository](https://apt.syncthing.net/) before applying this role.
+27
View File
@@ -0,0 +1,27 @@
---
# System user to run syncthing as
syncthing_user: syncthing
syncthing_group: syncthing
syncthing_home: /var/lib/syncthing
# Config directory (syncthing reads and writes this at runtime)
syncthing_config_dir: "{{ syncthing_home }}/.config/syncthing"
# GUI credentials (REQUIRED - must be set explicitly)
# syncthing_gui_user: "" # Intentionally undefined - role will fail if not set
# syncthing_gui_password: "" # Intentionally undefined - role will fail if not set
# GUI listen address and port
syncthing_gui_bind: "0.0.0.0"
syncthing_gui_port: 8384
# Sync protocol port (TCP)
syncthing_port: 22000
# Package and service names
syncthing_package: syncthing
syncthing_service: "syncthing@{{ syncthing_user }}"
# Firewall rules - list of allowed source ranges for GUI and sync ports
syncthing_allowed_networks:
- { src: "127.0.0.1/8", comment: "Localhost" }
+5
View File
@@ -0,0 +1,5 @@
---
- name: Restart syncthing
ansible.builtin.systemd:
name: "{{ syncthing_service }}"
state: restarted
+81
View File
@@ -0,0 +1,81 @@
---
- name: Validate required variables are set
ansible.builtin.assert:
that:
- syncthing_gui_user is defined
- syncthing_gui_user | length >= 1
- syncthing_gui_password is defined
- syncthing_gui_password | length >= 12
fail_msg: |
syncthing_gui_user and syncthing_gui_password are required.
syncthing_gui_password must be at least 12 characters.
See roles/syncthing/defaults/main.yml for configuration instructions.
- name: Install syncthing
ansible.builtin.package:
name: "{{ syncthing_package }}"
state: present
- name: Create syncthing system group
ansible.builtin.group:
name: "{{ syncthing_group }}"
system: true
state: present
- name: Create syncthing system user
ansible.builtin.user:
name: "{{ syncthing_user }}"
group: "{{ syncthing_group }}"
home: "{{ syncthing_home }}"
shell: /sbin/nologin
system: true
create_home: true
state: present
- name: Create syncthing config directory
ansible.builtin.file:
path: "{{ syncthing_config_dir }}"
state: directory
owner: "{{ syncthing_user }}"
group: "{{ syncthing_group }}"
mode: "0700"
- name: Check if syncthing config already exists
ansible.builtin.stat:
path: "{{ syncthing_config_dir }}/config.xml"
register: syncthing_config_stat
- name: Deploy initial syncthing config (skipped if already exists)
ansible.builtin.template:
src: config.xml.j2
dest: "{{ syncthing_config_dir }}/config.xml"
owner: "{{ syncthing_user }}"
group: "{{ syncthing_group }}"
mode: "0600"
when: not syncthing_config_stat.stat.exists
notify: Restart syncthing
- name: Allow syncthing GUI and sync traffic through firewall
community.general.ufw:
rule: allow
port: "{{ item.1.port }}"
proto: tcp
from: "{{ item.0.src }}"
direction: in
comment: "{{ item.0.comment }}"
loop: "{{ syncthing_allowed_networks | product(syncthing_ufw_ports) | list }}"
vars:
syncthing_ufw_ports:
- { port: "{{ syncthing_gui_port }}" }
- { port: "{{ syncthing_port }}" }
when: syncthing_allowed_networks | length > 0
retries: 5
delay: 2
register: ufw_result
until: ufw_result is succeeded
- name: Enable and start syncthing service
ansible.builtin.systemd:
name: "{{ syncthing_service }}"
enabled: true
state: started
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Managed by Ansible - initial bootstrap only, DO NOT EDIT MANUALLY -->
<!-- Syncthing will manage this file after first start -->
<configuration version="37">
<gui enabled="true" tls="false" debugging="false">
<address>{{ syncthing_gui_bind }}:{{ syncthing_gui_port }}</address>
<user>{{ syncthing_gui_user }}</user>
<!-- Plaintext password; syncthing will bcrypt-hash it on first start -->
<password>{{ syncthing_gui_password }}</password>
<theme>default</theme>
<insecureSkipHostcheck>false</insecureSkipHostcheck>
</gui>
<options>
<startBrowser>false</startBrowser>
<crashReportingEnabled>false</crashReportingEnabled>
<!-- Opt out of anonymous usage reporting -->
<urAccepted>-1</urAccepted>
<!-- Disable automatic upgrades (managed by package manager) -->
<autoUpgradeIntervalH>0</autoUpgradeIntervalH>
</options>
</configuration>