Setup of a multi-purpose home-server using Ansible: systemd, nftables, port-knocking, etckeeper, Let’s Encrypt, dynamic DNS, OpenLDAP, SSO, mail, PostgreSQL, Dotclear, Gitea, Nextcloud, NFS, XMPP, print & scan, DLNA, Transmission, iodine…
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

505 lines
15 KiB

---
# The home-server project produces a multi-purpose setup using Ansible.
# Copyright © 2018 Y. Gablin, under the GPL-3.0-or-later license.
# Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing.
### UPSTREAM BEGIN ⇒ ###
- name: pull prerequisites from upstream
include_role: name=etckeeper.inc allow_duplicates=true tasks_from=upstream.yml
vars:
msg: Nextcloud
### ⇐ UPSTREAM BEGIN ###
- name: install software
package:
name: "{{item}}"
state: present
with_items:
- mailcap
- uwsgi
- uwsgi-plugin-php
- nextcloud
- ffmpeg
- name: install AUR software
include_role:
name: aur.inc
allow_duplicates: true
vars:
packages:
- pkg: collabora-online-server-nodocker
pre: |
LANG=C sed -ri '
s/^(_I18N_EREGEX=).*$/\1{{loolwsd_lang}}/
' PKGBUILD
cat PKGBUILD
aur_user: git
- name: create the nextcloud user
user:
name: "{{nextcloud_user}}"
create_home: true
home: "{{nextcloud_data}}"
system: true
groups:
- users
### UPSTREAM END ⇒ ###
- name: merge upstream
include_role: name=etckeeper.inc allow_duplicates=true tasks_from=merge.yml
vars:
msg: Nextcloud
### ⇐ UPSTREAM END ###
- name: PostgreSQL user for Nextcloud
postgresql_user:
login_unix_socket: /run/shared_sockets
name: "{{nextcloud_db_user}}"
password: "{{nextcloud_db_password}}"
encrypted: true
become: true
become_user: postgres
- name: PostgreSQL database for Nextcloud
postgresql_db:
login_unix_socket: /run/shared_sockets
name: "{{nextcloud_db}}"
owner: "{{nextcloud_db_user}}"
become: true
become_user: postgres
#- name: change some loolwsd settings
# xml:
# path: /etc/loolwsd/loolwsd.xml
# xpath: "{{item.key}}"
# value: "{{item.value}}"
# with_dict:
# /config/server_name: '{{net_soa}}:443'
# /config/memproportion: '{{loolwsd_maxmem_asdouble}}'
# /config/ssl/enable: 'false'
# /config/ssl/termination: 'true'
# /config/admin_console/username: '{{loolwsd_admin_user}}'
# /config/admin_console/password: '{{loolwsd_admin_password}}'
# notify:
# - restart loolwsd.service
- name: change some loolwsd settings
lineinfile:
path: /etc/loolwsd/loolwsd.xml
backrefs: true
regexp: '^(.*<{{item.key}}\s[^>]*>)[^<]*(<.*)$'
line: '\g<1>{{item.value}}\2'
with_dict:
server_name: '{{net_soa}}:443'
memproportion: '{{loolwsd_maxmem_asdouble}}'
'enable\s[^>]*SSL[^>]*between loolwsd and the network': 'false'
termination: 'true'
'as_scheme\s[^>]*SSL': 'false'
'enable\s[^>]*SSL[^>]*between storage and loolwsd': 'false'
username: '{{loolwsd_admin_user}}'
password: '{{loolwsd_admin_password}}'
notify:
- restart loolwsd.service
- name: allow Nextcloud to connect to loolwsd
lineinfile:
path: /etc/loolwsd/loolwsd.xml
regexp: '<host\s.*{{net_soa | replace(".", "\\.")}}'
line: ' <host desc="Regex pattern of hostname to allow or deny." allow="true">(?:.*\.)?{{net_soa | replace(".", "\.")}}</host>'
insertafter: '<wopi desc="Allow/deny wopi storage.'
notify:
- restart loolwsd.service
- name: ensure Nextcloud ownership
block:
- name: ensure Nextcloud ownership — prepare file
shell: >
sed -r '
/%[CL]/ d;
s#%S/nextcloud#{{nextcloud_data}}#g;
s#%t#/var/tmp#g;
s/([[:blank:]]+nextcloud){2}$/ {{nextcloud_user}} {{nextcloud_user}}/
'
</usr/lib/tmpfiles.d/nextcloud.conf
>/tmp/nextcloud.conf
changed_when: false
- name: ensure Nextcloud ownership — install file
copy:
src: /tmp/nextcloud.conf
dest: /etc/tmpfiles.d/nextcloud.conf
remote_src: true
always:
- name: ensure Nextcloud ownership — cleanup
file:
path: /tmp/nextcloud.conf
state: absent
changed_when: false
- name: ensure Nextcloud ownership — apply
command: systemd-tmpfiles --create
changed_when: false
- name: send initial configuration
copy:
content: |
<?php
$CONFIG = array (
);
dest: "{{nextcloud_conf}}/config.php"
force: false
- name: check for multi-line arrays (reformated by nextcloud)
shell: >
grep -E '=>[[:blank:]]*($|array|\[)' "{{nextcloud_conf}}/config.php"
| grep -vE '[])],?[[:blank:]]*$' || true
register: check_conf_arrays_1
changed_when: false
- name: replace multi-line arrays (reformated by nextcloud)
shell: |
sed -rni '
: start
/=>[[:blank:]]*($|array|\[)/ b array
p;d
: array
/[])],?[[:blank:]]*$/ b check
N;b array
: check
h;n
/(["'"'"'])[^[:blank:]]+\1[[:blank:]]*=>|\);/ {
x
s/[[:blank:]]*[\r\n]+[[:blank:]]*/ /g
p;g
b start
}
H;x;b array' \
"{{nextcloud_conf}}/config.php"
args:
warn: false
when:
- (check_conf_arrays_1.stdout is defined)
- (check_conf_arrays_1.stdout != '')
- name: send the custom configuration that is needed for the setup
lineinfile:
path: "{{nextcloud_conf}}/config.php"
regexp: "^\\s*['\"]{{item.key}}['\"]\\s*="
line: " '{{item.key}}' => {{item.value}},"
insertbefore: '\);\s*$'
with_dict:
apps_paths: "array( 0 => array( 'path' => '{{nextcloud_root}}/apps', 'url' => '{{http_pfx_nextcloud}}/apps', 'writable' => false, ), 1 => array( 'path' => '{{nextcloud_data}}/apps', 'url' => '{{http_pfx_nextcloud}}/xapps', 'writable' => true, ), )"
check_for_working_htaccess: 'false'
memcache.local: "'\\\\OC\\\\Memcache\\\\APCu'"
overwritewebroot: "'{{http_pfx_nextcloud}}'"
skeletondirectory: "''"
tempdirectory: "'/var/tmp/nextcloud'"
overwrite.cli.url: "'https://{{net_soa}}{{http_pfx_nextcloud}}'"
notify:
- stop uwsgi@nextcloud.service
- restart uwsgi@nextcloud.socket
- name: ensure ownership of the nextcloud configuration file
file:
path: "{{nextcloud_conf}}/config.php"
owner: "{{nextcloud_user}}"
group: "{{nextcloud_user}}"
mode: 0640
- name: check that nextcloud is already configured
shell: >
grep -E "[\"']installed[\"'][[:blank:]]*=>[[:blank:]]*true"
"{{nextcloud_conf}}/config.php" || true
register: check_nextcloud_installed
changed_when: false
- name: run the installation script
command: >
/usr/bin/env NEXTCLOUD_CONFIG_DIR={{nextcloud_conf}}
/usr/bin/php ./occ maintenance:install
--database pgsql
--database-host "localhost:/run/shared_sockets"
--database-name "{{nextcloud_db}}"
--database-user "{{nextcloud_db_user}}"
--database-pass "{{nextcloud_db_password}}"
--admin-user "{{nextcloud_admin_user}}"
--admin-pass "{{nextcloud_admin_password}}"
--data-dir "{{nextcloud_data}}/data"
become: true
become_user: "{{nextcloud_user}}"
args:
chdir: "{{nextcloud_root}}"
when:
- ((check_nextcloud_installed.stdout is not defined) or (check_nextcloud_installed.stdout == ''))
- name: enable the ldap backend
command: >
/usr/bin/env NEXTCLOUD_CONFIG_DIR={{nextcloud_conf}}
/usr/bin/php ./occ app:enable user_ldap
become: true
become_user: "{{nextcloud_user}}"
args:
chdir: "{{nextcloud_root}}"
when:
- ((check_nextcloud_installed.stdout is not defined) or (check_nextcloud_installed.stdout == ''))
- name: create an empty ldap configuration
command: >
/usr/bin/env NEXTCLOUD_CONFIG_DIR={{nextcloud_conf}}
/usr/bin/php ./occ ldap:create-empty-config -p
become: true
become_user: "{{nextcloud_user}}"
args:
chdir: "{{nextcloud_root}}"
register: ldap_conf_num
when:
- ((check_nextcloud_installed.stdout is not defined) or (check_nextcloud_installed.stdout == ''))
- name: configure the ldap backend
command: >
/usr/bin/env NEXTCLOUD_CONFIG_DIR={{nextcloud_conf}}
/usr/bin/php ./occ ldap:set-config
'{{ldap_conf_num.stdout | default() | trim}}'
'{{item.key}}' '{{item.value}}'
become: true
become_user: "{{nextcloud_user}}"
args:
chdir: "{{nextcloud_root}}"
with_dict:
ldapBase: '{{ldap_root}}'
ldapBaseGroups: 'ou=Groups,{{ldap_root}}'
ldapBaseUsers: 'ou=Users,{{ldap_root}}'
ldapGidNumber: 'gidNumber'
ldapGroupDisplayName: 'cn'
ldapGroupFilterObjectclass: 'posixGroup'
ldapGroupMemberAssocAttr: 'gidNumber'
ldapHost: 'ldapi://%2Frun%2Fshared_sockets%2Fldapi/'
ldapLoginFilter: '(&(|(objectclass=posixAccount))(uid=%uid))'
ldapLoginFilterEmail: '0'
ldapLoginFilterUsername: '1'
ldapPort: '7636'
ldapTLS: '0'
ldapUserDisplayName: 'cn'
ldapUserFilter: '(|(objectclass=posixAccount))'
ldapUserFilterObjectclass: 'posixAccount'
ldapUuidGroupAttribute: 'auto'
ldapUuidUserAttribute: 'auto'
turnOnPasswordChange: '1'
useMemberOfToDetectMembership: '1'
ldapExpertUUIDGroupAttr: 'cn'
ldapExpertUUIDUserAttr: 'uid'
ldapConfigurationActive: '1'
when:
- ((check_nextcloud_installed.stdout is not defined) or (check_nextcloud_installed.stdout == ''))
- name: check for multi-line arrays (reformated by nextcloud)
shell: >
grep -E '=>[[:blank:]]*($|array|\[)' "{{nextcloud_conf}}/config.php"
| grep -vE '[])],?[[:blank:]]*$' || true
register: check_conf_arrays_2
changed_when: false
- name: replace multi-line arrays (reformated by nextcloud)
shell: |
sed -rni '
: start
/=>[[:blank:]]*($|array|\[)/ b array
p;d
: array
/[])],?[[:blank:]]*$/ b check
N;b array
: check
h;n
/(["'"'"'])[^[:blank:]]+\1[[:blank:]]*=>|\);/ {
x
s/[[:blank:]]*[\r\n]+[[:blank:]]*/ /g
p;g
b start
}
H;x;b array' \
"{{nextcloud_conf}}/config.php"
when:
- (check_conf_arrays_2.stdout is defined)
- (check_conf_arrays_2.stdout != '')
- name: send the rest of the custom configuration
lineinfile:
path: "{{nextcloud_conf}}/config.php"
regexp: "^\\s*['\"]{{item.key}}['\"]\\s*="
line: " '{{item.key}}' => {{item.value}},"
insertbefore: '\);\s*$'
with_dict:
datadirectory: "'{{nextcloud_data}}/data'"
dbhost: "'localhost:/run/shared_sockets'"
dbname: "'{{nextcloud_db}}'"
dbpassword: "'{{nextcloud_db_password}}'"
dbtype: "'pgsql'"
dbuser: "'{{nextcloud_db_user}}'"
default_phone_region: "'{{locales_default | truncate(2, True, '', 0) | upper}}'"
filelocking.enabled: 'false'
localstorage.allowsymlinks: 'true'
log.condition: " array ( )"
log_type: "'syslog'"
loglevel: 1
mail_domain: "'{{net_soa}}'"
mail_smtphost: "'{{DMZ}}'"
mail_smtpmode: "'smtp'"
mail_smtpport: 25
maintenance: 'false'
trusted_domains: "array ( 0 => 'localhost', 1 => '{{net_soa}}', )"
notify:
- stop uwsgi@nextcloud.service
- restart uwsgi@nextcloud.socket
- name: ensure ownership of the nextcloud configuration file
file:
path: "{{nextcloud_conf}}/config.php"
owner: "{{nextcloud_user}}"
group: "{{nextcloud_user}}"
mode: 0640
- name: send uwsgi configuration
template:
src: templates/nextcloud.ini.j2
dest: /etc/uwsgi/nextcloud.ini
mode: 0644
notify:
- stop uwsgi@nextcloud.service
- restart uwsgi@nextcloud.socket
- name: prepare to override some uwsgi settings for nextcloud
file:
path: "/etc/systemd/system/uwsgi@nextcloud.{{item}}.d"
state: directory
mode: 0755
with_items:
- service
- socket
- name: set the dependency on the sockets directory, and get socket activation
copy:
content: |
[Unit]
After=systemd-tmpfiles-setup.service
[Install]
Also=uwsgi@nextcloud.socket
dest: /etc/systemd/system/uwsgi@nextcloud.service.d/shared_sockets.conf
mode: 0644
- name: compute the list of nfs-exported directories, writeable by nextcloud
set_fact:
nextcloud_rw_nfs: '{{ nextcloud_rw_nfs | default("") }} {{ item.path }}'
with_items: "{{ nfs_exports }}"
- name: override the uwsgi service for nextcloud
copy:
content: |
[Service]
Restart=on-failure
SuccessExitStatus=0 1
PrivateDevices=yes
ProtectSystem=full
ReadWriteDirectories={{nextcloud_conf}} {{nextcloud_data}}{{nextcloud_rw_nfs}}
NoNewPrivileges=yes
User={{nextcloud_user}}
Group={{nextcloud_user}}
dest: /etc/systemd/system/uwsgi@nextcloud.service.d/secure-{{nickname}}.conf
mode: 0644
notify:
- stop uwsgi@nextcloud.service
- restart uwsgi@nextcloud.socket
- name: override the uwsgi socket for nextcloud
copy:
content: |
[Unit]
After=systemd-tmpfiles-setup.service
[Socket]
ListenStream=/run/shared_sockets/nextcloud
SocketUser={{nextcloud_user}}
SocketGroup={{nextcloud_user}}
SocketMode=0666
dest: /etc/systemd/system/uwsgi@nextcloud.socket.d/{{nickname}}.conf
mode: 0644
notify:
- stop uwsgi@nextcloud.service
- restart uwsgi@nextcloud.socket
- name: create a cron service for nextcloud
copy:
content: |
[Unit]
Description=Maintenance job for Nextcloud
[Service]
Environment=NEXTCLOUD_CONFIG_DIR={{nextcloud_conf}}
Type=oneshot
; https://help.nextcloud.com/t/11-0-2-incredibly-slow-login/9475/18
ExecStartPre=+-/usr/bin/su - postgres -c '/usr/bin/psql -d "{{nextcloud_db}}" -c "delete from oc_bruteforce_attempts;"'
ExecStart=/usr/bin/php -f {{nextcloud_root}}/cron.php
;ExecStartPost=-/usr/bin/find /var/lib/nextcloud/apps -type f -name '*.scss' -exec mv {} {}.{{nickname}}-disabled \;
PrivateDevices=yes
ProtectSystem=full
ReadWriteDirectories={{nextcloud_conf}} {{nextcloud_data}}
NoNewPrivileges=yes
User={{nextcloud_user}}
Group={{nextcloud_user}}
dest: /etc/systemd/system/nextcloud-maintenance.service
mode: 0644
notify:
- restart nextcloud-maintenance.timer
- name: create a cron timer for nextcloud
copy:
content: |
[Unit]
Description=Maintenance job for Nextcloud
[Timer]
OnBootSec=5min
OnUnitActiveSec=15min
[Install]
WantedBy=timers.target
dest: /etc/systemd/system/nextcloud-maintenance.timer
mode: 0644
notify:
- restart nextcloud-maintenance.timer
- name: upgrade Nextcloud in case an update occured
command: >
/usr/bin/env NEXTCLOUD_CONFIG_DIR={{nextcloud_conf}}
/usr/bin/php ./occ upgrade --no-interaction --no-ansi -q
become: true
become_user: "{{nextcloud_user}}"
args:
chdir: "{{nextcloud_root}}"
when:
- (check_nextcloud_installed.stdout is defined)
- (check_nextcloud_installed.stdout != '')
- name: enable loolwsd.service
systemd:
daemon_reload: true
name: loolwsd.service
enabled: true
- name: enable Nextcloud
systemd:
daemon_reload: true
name: uwsgi@nextcloud.socket
enabled: true
- name: enable Nextcloud maintenance
systemd:
daemon_reload: true
name: nextcloud-maintenance.timer
enabled: true
### LOCAL COMMIT ⇒ ###
- name: commit local changes
include_role: name=etckeeper.inc allow_duplicates=true tasks_from=local.yml
vars:
msg: Nextcloud
### ⇐ LOCAL COMMIT ###
- meta: flush_handlers