#!/bin/bash set -e services_path="/etc/yunohost/services.yml" mdns_path="/etc/yunohost/mdns.yml" do_init_regen() { if [[ $EUID -ne 0 ]]; then echo "You must be root to run this script" 1>&2 exit 1 fi cd /usr/share/yunohost/templates/yunohost [[ -d /etc/yunohost ]] || mkdir -p /etc/yunohost # set default current_host [[ -f /etc/yunohost/current_host ]] \ || echo "yunohost.org" > /etc/yunohost/current_host # copy default services, mdns, and firewall [[ -f $services_path ]] \ || cp services.yml "$services_path" [[ -f $mdns_path ]] \ || cp mdns.yml "$mdns_path" [[ -f /etc/yunohost/firewall.yml ]] \ || cp firewall.yml /etc/yunohost/firewall.yml # allow users to access /media directory [[ -d /etc/skel/media ]] \ || (mkdir -p /media && ln -s /media /etc/skel/media) # Cert folders mkdir -p /etc/yunohost/certs chown -R root:ssl-cert /etc/yunohost/certs chmod 750 /etc/yunohost/certs # App folders mkdir -p /etc/yunohost/apps chmod 700 /etc/yunohost/apps mkdir -p /home/yunohost.app chmod 755 /home/yunohost.app # Backup folders mkdir -p /home/yunohost.backup/archives chmod 750 /home/yunohost.backup/archives chown root:root /home/yunohost.backup/archives # This is later changed to admin:root once admin user exists # Empty ssowat json persistent conf echo "{}" > '/etc/ssowat/conf.json.persistent' chmod 644 /etc/ssowat/conf.json.persistent chown root:root /etc/ssowat/conf.json.persistent mkdir -p /var/cache/yunohost/repo chown root:root /var/cache/yunohost chmod 700 /var/cache/yunohost } do_pre_regen() { pending_dir=$1 cd /usr/share/yunohost/templates/yunohost # update services.yml if [[ -f $services_path ]]; then tmp_services_path="${services_path}-tmp" new_services_path="${services_path}-new" cp "$services_path" "$tmp_services_path" _update_services "$new_services_path" || { mv "$tmp_services_path" "$services_path" exit 1 } if [[ -f $new_services_path ]]; then # replace services.yml with new one mv "$new_services_path" "$services_path" mv "$tmp_services_path" "${services_path}-old" else rm -f "$tmp_services_path" fi else cp services.yml /etc/yunohost/services.yml fi mkdir -p $pending_dir/etc/cron.d/ mkdir -p $pending_dir/etc/cron.daily/ # add cron job for diagnosis to be ran at 7h and 19h + a random delay between # 0 and 20min, meant to avoid every instances running their diagnosis at # exactly the same time, which may overload the diagnosis server. cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF SHELL=/bin/bash 0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably" EOF # Cron job that upgrade the app list everyday cat > $pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog << EOF #!/bin/bash (sleep \$((RANDOM%3600)); yunohost tools update --apps > /dev/null) & EOF # Cron job that renew lets encrypt certificates if there's any that needs renewal cat > $pending_dir/etc/cron.daily/yunohost-certificate-renew << EOF #!/bin/bash yunohost domain cert-renew --email EOF # If we subscribed to a dyndns domain, add the corresponding cron # - delay between 0 and 60 secs to spread the check over a 1 min window # - do not run the command if some process already has the lock, to avoid queuing hundreds of commands... if ls -l /etc/yunohost/dyndns/K*.private 2>/dev/null then cat > $pending_dir/etc/cron.d/yunohost-dyndns << EOF SHELL=/bin/bash */10 * * * * root : YunoHost DynDNS update; sleep \$((RANDOM\\%60)); test -e /var/run/moulinette_yunohost.lock || yunohost dyndns update >> /dev/null EOF fi # legacy stuff to avoid yunohost reporting etckeeper as manually modified # (this make sure that the hash is null / file is flagged as to-delete) mkdir -p $pending_dir/etc/etckeeper touch $pending_dir/etc/etckeeper/etckeeper.conf # Skip ntp if inside a container (inspired from the conf of systemd-timesyncd) mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/ echo " [Unit] ConditionCapability=CAP_SYS_TIME ConditionVirtualization=!container " > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf # Make nftable conflict with yunohost-firewall mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/ cat > ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf << EOF [Unit] # yunohost-firewall and nftables conflict with each other Conflicts=yunohost-firewall.service ConditionFileIsExecutable=!/etc/init.d/yunohost-firewall ConditionPathExists=!/etc/systemd/system/multi-user.target.wants/yunohost-firewall.service EOF } do_post_regen() { regen_conf_files=$1 ###################### # Enfore permissions # ###################### chmod 750 /home/admin chmod 750 /home/yunohost.conf chmod 750 /home/yunohost.backup chmod 750 /home/yunohost.backup/archives chown root:root /home/yunohost.conf chown admin:root /home/yunohost.backup chown admin:root /home/yunohost.backup/archives # Certs # We do this with find because there could be a lot of them... chown -R root:ssl-cert /etc/yunohost/certs chmod 750 /etc/yunohost/certs find /etc/yunohost/certs/ -type f -exec chmod 640 {} \; find /etc/yunohost/certs/ -type d -exec chmod 750 {} \; find /etc/cron.*/yunohost-* -type f -exec chmod 755 {} \; find /etc/cron.d/yunohost-* -type f -exec chmod 644 {} \; find /etc/cron.*/yunohost-* -type f -exec chown root:root {} \; chown root:root /var/cache/yunohost chmod 700 /var/cache/yunohost chown root:root /var/cache/moulinette chmod 700 /var/cache/moulinette setfacl -m g:all_users:--- /var/www setfacl -m g:all_users:--- /var/log/nginx setfacl -m g:all_users:--- /etc/yunohost setfacl -m g:all_users:--- /etc/ssowat for USER in $(yunohost user list --quiet --output-as json | jq -r '.users | .[] | .username') do [ ! -e "/home/$USER" ] || setfacl -m g:all_users:--- /home/$USER done # Misc configuration / state files chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null) chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null) # Apps folder, custom hooks folder [[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d) [[ ! -e /etc/yunohost/apps ]] || (chown root /etc/yunohost/apps && chmod 700 /etc/yunohost/apps) # Create ssh.app and sftp.app groups if they don't exist yet grep -q '^ssh.app:' /etc/group || groupadd ssh.app grep -q '^sftp.app:' /etc/group || groupadd sftp.app # Propagates changes in systemd service config overrides [[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || { systemctl daemon-reload; systemctl restart ntp; } [[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload } _update_services() { python3 - << EOF import yaml with open('services.yml') as f: new_services = yaml.load(f) with open('/etc/yunohost/services.yml') as f: services = yaml.load(f) or {} updated = False for service, conf in new_services.items(): # remove service with empty conf if conf is None: if service in services: print("removing '{0}' from services".format(service)) del services[service] updated = True # add new service elif not services.get(service, None): print("adding '{0}' to services".format(service)) services[service] = conf updated = True # update service conf else: conffiles = services[service].pop('conffiles', {}) # status need to be removed if "status" not in conf and "status" in services[service]: print("update '{0}' service status access".format(service)) del services[service]["status"] updated = True if services[service] != conf: print("update '{0}' service".format(service)) services[service].update(conf) updated = True if conffiles: services[service]['conffiles'] = conffiles # Remove legacy /var/log/daemon.log and /var/log/syslog from log entries # because they are too general. Instead, now the journalctl log is # returned by default which is more relevant. if "log" in services[service]: if services[service]["log"] in ["/var/log/syslog", "/var/log/daemon.log"]: del services[service]["log"] if updated: with open('/etc/yunohost/services.yml-new', 'w') as f: yaml.safe_dump(services, f, default_flow_style=False) EOF } FORCE=${2:-0} DRY_RUN=${3:-0} case "$1" in pre) do_pre_regen $4 ;; post) do_post_regen $4 ;; init) do_init_regen ;; *) echo "hook called with unknown argument \`$1'" >&2 exit 1 ;; esac exit 0