Installer.mk 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. SHELL := /bin/bash
  2. SERVER_NAME := $(shell bin/tcms-hostname)
  3. USER_NAME := $(shell bin/tcms-hostname --user)
  4. .PHONY: depend
  5. depend:
  6. [ -f "/etc/debian_version" ] && make -f Installer.mk prereq-debs; /bin/true;
  7. make -f Installer.mk prereq-perl prereq-frontend
  8. .PHONY: install
  9. install:
  10. test -d www/themes || mkdir -p www/themes
  11. test -d data/files || mkdir -p data/files
  12. test -d www/assets || mkdir -p www/assets
  13. test -d www/statics || mkdir -p www/statics
  14. test -d totp/ || mkdir -p totp
  15. test -d ~/.tcms || mkdir ~/.tcms
  16. test -d logs/ && mkdir -p logs/; /bin/true
  17. $(RM) pod2htmd.tmp;
  18. .PHONY: service-user
  19. service-user:
  20. sudo useradd -MU -s /sbin/nologin -d "$(shell pwd)" $(USER_NAME); /bin/true
  21. sudo chown -R $(USER_NAME):$(USER_NAME) .
  22. # Can be 760 if you aren't using git features as a developer user that is not the system user.
  23. sudo chmod -R 0770 .
  24. # For some reason, nginx needs world readability to see the socket, despite having group permissions.
  25. # Seems pretty dumb to me, but whatever. We are locking every single other file away from it & other users.
  26. sudo chmod 0755 .
  27. sudo chmod 0775 run
  28. sudo chown -R $(USER_NAME):www-data run
  29. sudo chmod -R 0770 bin/ tcms www/server.psgi
  30. sudo -u $(USER_NAME) mkdir 0700 .ssh
  31. sudo -u $(USER_NAME) touch .ssh/authorized_keys
  32. sudo -u $(USER_NAME) chmod 0600 .ssh/authorized_keys
  33. .PHONY: install-service
  34. install-service: #service-user
  35. sudo systemctl disable $(SERVER_NAME); /bin/true
  36. cp service-files/systemd.unit service-files/$(SERVER_NAME).service
  37. sed -i 's#__DOMAIN__#$(SERVER_NAME)#g' service-files/$(SERVER_NAME).service
  38. sed -i 's#__USER__#$(USER_NAME)#g' service-files/$(SERVER_NAME).service
  39. sed -i 's#__REPLACEME__#$(shell pwd)#g' service-files/$(SERVER_NAME).service
  40. sudo ln -sr service-files/$(SERVER_NAME).service /usr/lib/systemd/system/$(SERVER_NAME).service; /bin/true
  41. sudo systemctl daemon-reload
  42. sudo systemctl enable $(SERVER_NAME)
  43. sudo systemctl start $(SERVER_NAME)
  44. .PHONY: prereq-debian
  45. prereq-debian: prereq-debs prereq-perl prereq-frontend prereq-node
  46. .PHONY: prereq-debs
  47. prereq-debs:
  48. sudo apt-get update
  49. sudo apt-get install -y sqlite3 nodejs npm libsqlite3-dev libdbd-sqlite3-perl cpanminus starman libxml2 curl cmake \
  50. uwsgi uwsgi-plugin-psgi fail2ban nginx certbot postfix dovecot-imapd dovecot-pop3d postgrey spamassassin amavis clamav\
  51. opendmarc opendkim opendkim-tools libunbound-dev \
  52. libtext-xslate-perl libplack-perl libconfig-tiny-perl libdatetime-format-http-perl libjson-maybexs-perl \
  53. libuuid-tiny-perl libcapture-tiny-perl libconfig-simple-perl libdbi-perl libfile-slurper-perl libfile-touch-perl \
  54. libfile-copy-recursive-perl libxml-rss-perl libmodule-install-perl libio-string-perl uuid-dev \
  55. libmoose-perl libmoosex-types-datetime-perl libxml-libxml-perl liblist-moreutils-perl libclone-perl libpath-tiny-perl \
  56. selinux-utils setools policycoreutils-python-utils policycoreutils selinux-basics auditd \
  57. pdns-tools pdns-server pdns-backend-sqlite3 libmagic-dev autotools-dev dh-autoreconf
  58. .PHONY: prereq-perl
  59. prereq-perl:
  60. sudo cpanm -n --installdeps .
  61. .PHONY: prereq-node
  62. prereq-node:
  63. npm i
  64. .PHONY: prereq-frontend
  65. prereq-frontend:
  66. mkdir -p www/scripts; pushd www/scripts && curl -L --remote-name-all \
  67. "https://raw.githubusercontent.com/chalda-pnuzig/emojis.json/master/dist/list.min.json" \
  68. "https://raw.githubusercontent.com/highlightjs/cdn-release/main/build/highlight.min.js" \
  69. "https://cdn.jsdelivr.net/npm/chart.js" \
  70. "https://raw.githubusercontent.com/hakimel/reveal.js/master/dist/reveal.js"; popd
  71. mkdir -p www/styles; pushd www/styles && curl -L --remote-name-all \
  72. "https://raw.githubusercontent.com/highlightjs/cdn-release/main/build/styles/obsidian.min.css" \
  73. "https://raw.githubusercontent.com/hakimel/reveal.js/master/dist/reveal.css" \
  74. "https://raw.githubusercontent.com/hakimel/reveal.js/master/dist/theme/white.css"; popd
  75. mv www/styles/white.css www/styles/reveal-white.css
  76. sed -i 's/Source Sans Pro,//g' www/styles/reveal-white.css
  77. .PHONY: reset
  78. reset: reset-remove install
  79. .PHONY: reset-remove
  80. reset-remove:
  81. rm -rf data; /bin/true
  82. rm -rf www/themes; /bin/true
  83. rm -rf www/assets; /bin/true
  84. rm config/auth.db; /bin/true
  85. rm config/main.cfg; /bin/true
  86. rm config/has_users; /bin/true
  87. rm config/setup; /bin/true
  88. .PHONY: fail2ban
  89. fail2ban:
  90. cp fail2ban/tcms-jail.tmpl fail2ban/tcms-jail.conf
  91. sed -i 's#__LOGDIR__#$(shell pwd)#g' fail2ban/tcms-jail.conf
  92. sed -i 's#__DOMAIN__#$(SERVER_NAME)#g' fail2ban/tcms-jail.conf
  93. sudo rm /etc/fail2ban/jail.d/$(SERVER_NAME).conf; /bin/true
  94. sudo rm /etc/fail2ban/filter.d/$(SERVER_NAME).conf; /bin/true
  95. sudo ln -sr fail2ban/tcms-jail.conf /etc/fail2ban/jail.d/$(SERVER_NAME).conf
  96. sudo ln -sr fail2ban/tcms-filter.conf /etc/fail2ban/filter.d/$(SERVER_NAME).conf
  97. sudo systemctl reload fail2ban
  98. .PHONY: nginx
  99. nginx:
  100. [ -n "$$SERVER_NAME" ] || ( echo "Please set the SERVER_NAME environment variable before running (e.g. test.test)" && /bin/false )
  101. sed 's/\%SERVER_NAME\%/$(SERVER_NAME)/g' nginx/tcms.conf.tmpl > nginx/tcms.conf.intermediate
  102. sed 's/\%SERVER_SOCK\%/$(shell pwd)/g' nginx/tcms.conf.intermediate > nginx/tcms.conf
  103. rm nginx/tcms.conf.intermediate
  104. mkdir run
  105. chown $(USER_NAME):www-data run
  106. chmod 0770 run
  107. sudo mkdir -p '/var/www/$(SERVER_NAME)'
  108. sudo mkdir -p '/var/www/mail.$(SERVER_NAME)'
  109. sudo mkdir -p '/etc/letsencrypt/live/$(SERVER_NAME)'
  110. [ -e "/etc/nginx/sites-enabled/$$SERVER_NAME.conf" ] && sudo rm "/etc/nginx/sites-enabled/$$SERVER_NAME.conf"; /bin/true
  111. sudo ln -sr nginx/tcms.conf '/etc/nginx/sites-enabled/$(SERVER_NAME).conf'
  112. # Make a self-signed cert FIRST, because certbot has a chicken/egg problem
  113. sudo openssl req -x509 -config etc/openssl.conf -nodes -newkey rsa:4096 -subj '/CN=$(SERVER_NAME)' -addext 'subjectAltName=DNS:www.$(SERVER_NAME),DNS:mail.$(SERVER_NAME)' -keyout '/etc/letsencrypt/live/$(SERVER_NAME)/privkey.pem' -out '/etc/letsencrypt/live/$(SERVER_NAME)/fullchain.pem' -days 365
  114. sudo systemctl reload nginx
  115. # Now run certbot and get that http dcv. We have to do a "gamer move" so that certbot doesn't complain about live dir existing.
  116. sudo rm -rf '/etc/letsencrypt/live/$(SERVER_NAME)'
  117. sudo certbot certonly --webroot -w '/var/www/$(SERVER_NAME)/' -d '$(SERVER_NAME)' -d 'www.$(SERVER_NAME)' -w '/var/www/mail.$(SERVER_NAME)' -d 'mail.$(SERVER_NAME)'
  118. sudo systemctl reload nginx
  119. .PHONY: mail
  120. mail: dkim dmarc
  121. # Dovecot
  122. sudo cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig
  123. sudo sed -i 's/^\(ssl_cert\s*=\).*/\1<\/etc\/letsencrypt\/live\/$(SERVER_NAME)\/fullchain.pem/g' /etc/dovecot/conf.d/10-ssl.conf
  124. sudo sed -i 's/^\(ssl_key\s*=\).*/\1\<\/etc\/letsencrypt\/live\/$(SERVER_NAME)\/privkey.pem/g' /etc/dovecot/conf.d/10-ssl.conf
  125. # Postfix
  126. sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
  127. sudo sed -i 's/^\(smtpd_tls_cert_file\s*=\).*/\1\/etc\/letsencrypt\/live\/$(SERVER_NAME)\/fullchain.pem/g' /etc/postfix/main.cf
  128. sudo sed -i 's/^\(smtpd_tls_key_file\s*=\).*/\1\/etc\/letsencrypt\/live\/$(SERVER_NAME)\/privkey.pem/g' /etc/postfix/main.cf
  129. # XXX we should not do these two.
  130. sudo sed -i 's/^\(myhostname\s*=\).*/\1$(SERVER_NAME)/g' /etc/postfix/main.cf
  131. sudo echo '$(SERVER_NAME)' > /etc/mailname
  132. # Configure postfix to put on its socks and shoes. This all implicitly relies on good defaults in the opendkim/opendmarc packages.
  133. sudo postconf -e milter_default_action=accept
  134. sudo postconf -e milter_protocol=2
  135. sudo postconf -e smtpd_milters=local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock
  136. sudo postconf -e non_smtpd_milters=\$smtpd_milters
  137. sudo service postfix reload
  138. # TODO setup various mail aliases and so forth, e.g. postmaster@, soa@, the various lists etc
  139. .PHONY: dkim
  140. dkim:
  141. sudo mkdir -p /etc/opendkim/keys/$(SERVER_NAME)
  142. sudo opendkim-genkey --directory /etc/opendkim/keys/$(SERVER_NAME) -s mail -d $(SERVER_NAME)
  143. sudo openssl rsa -in /etc/opendkim/keys/$(SERVER_NAME)/mail.private -pubout > /tmp/mail.public
  144. sudo mv /tmp/mail.public /etc/opendkim/keys/$(SERVER_NAME)/mail.public
  145. sudo chown -R opendkim:opendkim /etc/opendkim
  146. sudo mail/mongle_dkim_config $(SERVER_NAME)
  147. sudo service opendkim enable
  148. sudo service opendkim start
  149. .PHONY: dmarc
  150. dmarc:
  151. sudo mail/mongle_dmarc_config $(SERVER_NAME) mail.$(SERVER_NAME)
  152. sudo service opendmarc enable
  153. sudo service opendmarc start
  154. .PHONY: dns
  155. dns:
  156. cp dns/tcms.tmpl dns/tcms.conf
  157. sed -i 's#__DIR__#$(shell pwd)#g' dns/tcms.conf
  158. sed -i 's#__DOMAIN__#$(SERVER_NAME)#g' dns/tcms.conf
  159. [[ -e /etc/powerdns/pdns.d/$(SERVER_NAME).conf ]] && sudo rm /etc/powerdns/pdns.d/$(SERVER_NAME).conf
  160. sudo cp dns/tcms.conf /etc/powerdns/pdns.d/$(SERVER_NAME).conf
  161. sudo mkdir /etc/systemd/resolved.conf.d/; /bin/true
  162. sudo cp dns/10-disable-stub-resolver.conf /etc/systemd/resolved.conf.d/
  163. sudo chown -R systemd-resolve:systemd-resolve /etc/systemd/resolved.conf.d/
  164. sudo chmod 0660 /etc/systemd/resolved.conf.d/10-disable-stub-resolver.conf
  165. sudo systemctl restart systemd-resolved
  166. # Build the zone database and initialize the zone for our domain
  167. rm dns/zones.db; /bin/true
  168. sqlite3 dns/zones.db < /usr/share/pdns-backend-sqlite3/schema/schema.sqlite3.sql
  169. bin/build_zone > dns/default.zone
  170. zone2sql --gsqlite --zone=dns/default.zone --zone-name=$(SERVER_NAME) > dns/default.zone.sql
  171. sqlite3 dns/zones.db < dns/default.zone.sql
  172. # Bind mount our dns/ folder so that pdns can see it in chroot
  173. sudo mkdir /var/spool/powerdns/$(SERVER_NAME); /bin/true
  174. sudo chown pdns:pdns /var/spool/powerdns/$(SERVER_NAME); /bin/true
  175. sudo cp /etc/fstab /tmp/fstab.new
  176. sudo chown $(USER) /tmp/fstab.new
  177. echo "$(shell pwd)/dns /var/spool/powerdns/$(SERVER_NAME) none defaults,bind 0 0" >> /tmp/fstab.new
  178. sort < /tmp/fstab.new | uniq | grep -o '^[^#]*' > /tmp/fstab.new
  179. sudo chown root:root /tmp/fstab.new
  180. sudo mv /etc/fstab /etc/fstab.bak
  181. sudo mv /tmp/fstab.new /etc/fstab
  182. sudo mount /var/spool/powerdns/$(SERVER_NAME)
  183. # Don't need no bind
  184. [[ -e /etc/powerdns/pdns.d/bind.conf ]] && sudo rm /etc/powerdns/pdns.d/bind.conf
  185. # Fix broken service configuration
  186. sudo dns/configure_pdns
  187. sudo chown $(USER_NAME):pdns dns/
  188. sudo chown $(USER_NAME):pdns dns/zones.db
  189. sudo cp dns/10-powerdns.conf /etc/rsyslog.d/10-powerdns.conf
  190. sudo systemctl daemon-reload
  191. sudo service rsyslog restart
  192. sudo service pdns enable
  193. sudo service pdns start
  194. .PHONY: githook
  195. githook:
  196. cp git-hooks/pre-commit .git/hooks
  197. .PHONY: firewall
  198. firewall:
  199. # Remove dopey unauthenticated port for git from /etc/services
  200. sudo sed -i '/^git\s/d' /etc/services
  201. sudo cp ufw/git ufw/pdns_server /etc/ufw/applications.d
  202. sudo ufw/setup-rules
  203. .PHONY: all
  204. all: prereq-debian install fail2ban nginx mail dns firewall githook