diff --git a/roles/autossh/defaults/main.yaml b/roles/autossh/defaults/main.yaml new file mode 100644 index 0000000..e319a85 --- /dev/null +++ b/roles/autossh/defaults/main.yaml @@ -0,0 +1,17 @@ +--- +autossh_package_name: autossh +autossh_package_state: present + +autossh_service_name: autossh@.service +autossh_systemd_unit_path: /etc/systemd/system/autossh@.service + +autossh_etc_path: /etc/autossh +autossh_run_path: /run/autossh + +autossh_user: autossh +autossh_group: autossh +autossh_user_state: present +autossh_user_comment: AutoSSH +autossh_user_home: "/home/{{ autossh_user }}" +autossh_user_password: "!" +autossh_user_shell: /usr/sbin/nologin diff --git a/roles/autossh/handlers/main.yaml b/roles/autossh/handlers/main.yaml new file mode 100644 index 0000000..e7a5e8a --- /dev/null +++ b/roles/autossh/handlers/main.yaml @@ -0,0 +1,20 @@ +--- +- name: autossh daemon-reload + systemd: + daemon_reload: yes + +- name: reload autossh + service: + name: "{{ autossh_service_name }}" + state: reloaded + +- name: restart autossh + service: + name: "{{ autossh_service_name }}" + state: restarted + +- name: reload autossh instances + service: + name: "autossh@{{ item.name }}.service" + state: restarted + loop: "{{ autossh_config | default([]) }}" diff --git a/roles/autossh/tasks/keys.yaml b/roles/autossh/tasks/keys.yaml new file mode 100644 index 0000000..9039696 --- /dev/null +++ b/roles/autossh/tasks/keys.yaml @@ -0,0 +1,28 @@ +--- +- set_fact: + key_path: "{{ autossh_user_home }}/.ssh/{{ item }}" + +- name: "install private key ({{ item }})" + copy: + dest: "{{ autossh_user_home }}/.ssh/{{ item }}" + content: "{{ lookup('vars', 'autossh_private_key_' + item) }}" + owner: "{{ autossh_user }}" + group: "{{ autossh_group }}" + mode: 0600 + when: lookup('vars', 'autossh_private_key_' + item, default='') | length + +- name: "determine if private key exists ({{ item }})" + stat: + path: "{{ key_path }}" + register: priv_key + +- name: "determine if public key exists ({{ item }}.pub)" + stat: + path: "{{ key_path }}.pub" + register: pub_key + +- name: "derive public key ({{ item }})" + shell: "ssh-keygen -y -f {{ key_path }} > {{ key_path }}.pub" + when: + - not pub_key.stat.exists + - priv_key.stat.exists diff --git a/roles/autossh/tasks/main.yaml b/roles/autossh/tasks/main.yaml new file mode 100644 index 0000000..f0dc374 --- /dev/null +++ b/roles/autossh/tasks/main.yaml @@ -0,0 +1,80 @@ +--- +- name: "create {{ autossh_user }} user" + user: + name: "{{ autossh_user }}" + comment: "{{ autossh_user_comment }}" + password: "{{ autossh_user_password }}" + #password_lock: yes + shell: "{{ autossh_user_shell }}" + generate_ssh_key: yes + state: "{{ autossh_user_state }}" + system: yes + skeleton: /dev/null + +- name: "manage keys {{ item }}" + include: keys.yaml + loop: + - id_dsa + - id_ecdsa + - id_ed25519 + - id_rsa + +- name: create directories + file: + path: "{{ item }}" + owner: root + group: root + mode: 0755 + state: directory + loop: + - "{{ autossh_etc_path }}" + - "{{ autossh_run_path }}" + +- name: install package + package: + name: "{{ autossh_package_name }}" + state: "{{ autossh_package_state }}" +- name: manage keys "{{ item }}" + include: keys.yaml + loop: + - id_dsa + - id_ecdsa + - id_ed25519 + - id_rsa + +- name: manage authorized keys + authorized_key: + user: "{{ autossh_user }}" + key: "{{ item.key }}" + comment: "{{ item.comment | default(omit) }}" + state: "{{ item.state | default('present') }}" + loop: "{{ autossh_authorized_keys | default([]) }}" + +- name: configure systemd unit + template: + src: autossh.service.j2 + dest: "{{ autossh_systemd_unit_path }}" + owner: root + group: root + mode: 0644 + notify: + - reload autossh instances + - autossh daemon-reload + when: ansible_service_mgr == 'systemd' + +- name: configure autossh tunnels + template: + src: autossh.j2 + dest: "{{ autossh_etc_path }}/{{ item.name }}" + owner: root + group: root + mode: 0644 + loop: "{{ autossh_config | default([]) }}" + notify: reload autossh instances + +- name: manage services + service: + name: "autossh@{{ item.name }}.service" + state: "{{ item.state | default('started') }}" + enabled: "{{ item.enabled | default(true) }}" + loop: "{{ autossh_config | default([]) }}" diff --git a/roles/autossh/templates/autossh.j2 b/roles/autossh/templates/autossh.j2 new file mode 100644 index 0000000..18c4a25 --- /dev/null +++ b/roles/autossh/templates/autossh.j2 @@ -0,0 +1,8 @@ +# {{ ansible_managed }} + +AUTOSSH_POLL=60 +AUTOSSH_FIRST_POLL=30 +AUTOSSH_GATETIME=0 +AUTOSSH_PORT=22000 +SSH_OPTIONS="{{ item.options | join(' ') }}" +SSH_HOST={{ item.host }} diff --git a/roles/autossh/templates/autossh.service.j2 b/roles/autossh/templates/autossh.service.j2 new file mode 100644 index 0000000..535a0b9 --- /dev/null +++ b/roles/autossh/templates/autossh.service.j2 @@ -0,0 +1,19 @@ +# {{ ansible_managed }} + +[Unit] +Description=autossh %I +Wants=network-online.target +After=network-online.target + +[Service] +Type=simple +User={{ autossh_user }} +EnvironmentFile={{ autossh_etc_path }}/%i +ExecStart= +ExecStart=/usr/bin/autossh -C -q -l {{ autossh_user }} -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=15 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=no $SSH_OPTIONS $SSH_HOST +Restart=always +RestartSec=60 +PIDFile={{ autossh_run_path }}/%i.pid + +[Install] +WantedBy=multi-user.target