freedombone-app-akaunting 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. #!/bin/bash
  2. #
  3. # .---. . .
  4. # | | |
  5. # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
  6. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
  7. # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
  8. #
  9. # Freedom in the Cloud
  10. #
  11. # Personal or small business accounts
  12. #
  13. # License
  14. # =======
  15. #
  16. # Copyright (C) 2018 Bob Mottram <bob@freedombone.net>
  17. #
  18. # This program is free software: you can redistribute it and/or modify
  19. # it under the terms of the GNU Affero General Public License as published by
  20. # the Free Software Foundation, either version 3 of the License, or
  21. # (at your option) any later version.
  22. #
  23. # This program is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. # GNU Affero General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU Affero General Public License
  29. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  30. VARIANTS='full full-vim media'
  31. IN_DEFAULT_INSTALL=0
  32. SHOW_ON_ABOUT=1
  33. AKAUNTING_DOMAIN_NAME=
  34. AKAUNTING_CODE=
  35. AKAUNTING_ONION_PORT=8341
  36. AKAUNTING_REPO="https://github.com/akaunting/akaunting"
  37. AKAUNTING_COMMIT='b68c840cded60d92b86e98fcbc26ce338cf93fef'
  38. AKAUNTING_ADMIN_PASSWORD=
  39. AKAUNTING_BACKGROUND_IMAGE_URL=
  40. akaunting_variables=(ONION_ONLY
  41. AKAUNTING_DOMAIN_NAME
  42. AKAUNTING_CODE
  43. DDNS_PROVIDER
  44. MY_USERNAME)
  45. function akaunting_remove_bad_links {
  46. cd "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" || exit 365873658
  47. # copy jquery locally
  48. jquery_version='1.12.4'
  49. if [ ! -f jquery-${jquery_version}.js ]; then
  50. cd "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" || exit 3276324
  51. wget https://code.jquery.com/jquery-${jquery_version}.js
  52. jquery_hash=$(sha256sum jquery-${jquery_version}.js | awk -F ' ' '{print $1}')
  53. if [[ "$jquery_hash" != '430f36f9b5f21aae8cc9dca6a81c4d3d84da5175eaedcf2fdc2c226302cb3575' ]]; then
  54. echo $'Unexpected jquery hash value'
  55. exit 78363527
  56. fi
  57. fi
  58. sed -i '/googleapi/d' resources/assets/sass/app.scss
  59. sed -i "s|ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js|$AKAUNTING_DOMAIN_NAME/jquery-${jquery_version}.js|g" vendor/league/flysystem/docs/_layouts/default.html
  60. sed -i '/googleapi/d' vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/views/503.blade.php
  61. sed -i '/googleapi/d' vendor/almasaeed2010/adminlte/build/less/AdminLTE-without-plugins.less
  62. sed -i '/googleapi/d' vendor/almasaeed2010/adminlte/build/less/AdminLTE.less
  63. sed -i '/googleapi/d' vendor/almasaeed2010/adminlte/dist/css/AdminLTE.css
  64. sed -i '/googleapi/d' vendor/almasaeed2010/adminlte/dist/css/AdminLTE.min.css
  65. sed -i '/googleapi/d' vendor/almasaeed2010/adminlte/dist/css/alt/AdminLTE-without-plugins.css
  66. sed -i '/googleapi/d' vendor/almasaeed2010/adminlte/dist/css/alt/AdminLTE-without-plugins.min.css
  67. sed -i "s|ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js|$AKAUNTING_DOMAIN_NAME/jquery-${jquery_version}.js|g" vendor/almasaeed2010/adminlte/plugins/ckeditor/samples/old/jquery.html
  68. chown -R www-data:www-data "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs"
  69. }
  70. function logging_on_akaunting {
  71. echo -n ''
  72. }
  73. function logging_off_akaunting {
  74. echo -n ''
  75. }
  76. function remove_user_akaunting {
  77. remove_username="$1"
  78. "${PROJECT_NAME}-pass" -u "$remove_username" --rmapp akaunting
  79. }
  80. function add_user_akaunting {
  81. new_username="$1"
  82. new_user_password="$2"
  83. "${PROJECT_NAME}-pass" -u "$new_username" -a akaunting -p "$new_user_password"
  84. echo '0'
  85. }
  86. function install_interactive_akaunting {
  87. if [ ! "$ONION_ONLY" ]; then
  88. ONION_ONLY='no'
  89. fi
  90. if [[ "$ONION_ONLY" != "no" ]]; then
  91. AKAUNTING_DOMAIN_NAME='akaunting.local'
  92. else
  93. AKAUNTING_DETAILS_COMPLETE=
  94. while [ ! $AKAUNTING_DETAILS_COMPLETE ]
  95. do
  96. data=$(mktemp 2>/dev/null)
  97. if [[ $DDNS_PROVIDER == "default@freedns.afraid.org" ]]; then
  98. dialog --backtitle $"Freedombone Configuration" \
  99. --title $"Akaunting Configuration" \
  100. --form $"\\nPlease enter your Akaunting details.\\n\\nIMPORTANT: This should be a domain name which is supported by Let's Encrypt:" 14 65 2 \
  101. $"Domain:" 1 1 "$(grep 'AKAUNTING_DOMAIN_NAME' temp.cfg | awk -F '=' '{print $2}')" 1 25 33 40 \
  102. $"Code:" 2 1 "$(grep 'AKAUNTING_CODE' temp.cfg | awk -F '=' '{print $2}')" 2 25 33 255 \
  103. 2> "$data"
  104. else
  105. dialog --backtitle $"Freedombone Configuration" \
  106. --title $"Akaunting Configuration" \
  107. --form $"\\nPlease enter your Akaunting details.\\n\\nIMPORTANT: This should be a domain name which is supported by Let's Encrypt:" 14 65 2 \
  108. $"Domain:" 1 1 "$(grep 'AKAUNTING_DOMAIN_NAME' temp.cfg | awk -F '=' '{print $2}')" 1 25 33 40 \
  109. 2> "$data"
  110. fi
  111. sel=$?
  112. case $sel in
  113. 1) rm -f "$data"
  114. exit 1;;
  115. 255) rm -f "$data"
  116. exit 1;;
  117. esac
  118. AKAUNTING_DOMAIN_NAME=$(sed -n 1p < "$data")
  119. if [ "$AKAUNTING_DOMAIN_NAME" ]; then
  120. if [[ $AKAUNTING_DOMAIN_NAME == "$HUBZILLA_DOMAIN_NAME" ]]; then
  121. AKAUNTING_DOMAIN_NAME=""
  122. fi
  123. TEST_DOMAIN_NAME=$AKAUNTING_DOMAIN_NAME
  124. validate_domain_name
  125. if [[ "$TEST_DOMAIN_NAME" != "$AKAUNTING_DOMAIN_NAME" ]]; then
  126. AKAUNTING_DOMAIN_NAME=
  127. dialog --title $"Domain name validation" --msgbox "$TEST_DOMAIN_NAME" 15 50
  128. else
  129. if [[ $DDNS_PROVIDER == "default@freedns.afraid.org" ]]; then
  130. AKAUNTING_CODE=$(sed -n 2p < "$data")
  131. validate_freedns_code "$AKAUNTING_CODE"
  132. if [ ! "$VALID_CODE" ]; then
  133. AKAUNTING_DOMAIN_NAME=
  134. fi
  135. fi
  136. fi
  137. fi
  138. if [ $AKAUNTING_DOMAIN_NAME ]; then
  139. AKAUNTING_DETAILS_COMPLETE="yes"
  140. fi
  141. rm -f "$data"
  142. done
  143. write_config_param "AKAUNTING_CODE" "$AKAUNTING_CODE"
  144. fi
  145. write_config_param "AKAUNTING_DOMAIN_NAME" "$AKAUNTING_DOMAIN_NAME"
  146. APP_INSTALLED=1
  147. }
  148. function change_password_akaunting {
  149. curr_username="$1"
  150. new_user_password="$2"
  151. read_config_param 'AKAUNTING_DOMAIN_NAME'
  152. "${PROJECT_NAME}-pass" -u "$curr_username" -a akaunting -p "$new_user_password"
  153. }
  154. function akaunting_create_database {
  155. if [ -f "$IMAGE_PASSWORD_FILE" ]; then
  156. AKAUNTING_ADMIN_PASSWORD="$(printf "%s" "$(cat "$IMAGE_PASSWORD_FILE")")"
  157. else
  158. if [ ! "$AKAUNTING_ADMIN_PASSWORD" ]; then
  159. AKAUNTING_ADMIN_PASSWORD="$(create_password "${MINIMUM_PASSWORD_LENGTH}")"
  160. fi
  161. fi
  162. if [ ! "$AKAUNTING_ADMIN_PASSWORD" ]; then
  163. return
  164. fi
  165. function_check create_database
  166. create_database akaunting "$AKAUNTING_ADMIN_PASSWORD" "$MY_USERNAME"
  167. }
  168. function reconfigure_akaunting {
  169. echo -n ''
  170. }
  171. function upgrade_akaunting {
  172. CURR_AKAUNTING_COMMIT=$(get_completion_param "akaunting commit")
  173. if [[ "$CURR_AKAUNTING_COMMIT" == "$AKAUNTING_COMMIT" ]]; then
  174. return
  175. fi
  176. if grep -q "akaunting domain" "$COMPLETION_FILE"; then
  177. AKAUNTING_DOMAIN_NAME=$(get_completion_param "akaunting domain")
  178. fi
  179. # update to the next commit
  180. function_check set_repo_commit
  181. set_repo_commit "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" "akaunting commit" "$AKAUNTING_COMMIT" "$AKAUNTING_REPO"
  182. cd "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" || exit 367835
  183. install_composer
  184. akaunting_remove_bad_links
  185. chown -R www-data:www-data "/var/www/${AKAUNTING_DOMAIN_NAME}/htdocs"
  186. }
  187. function backup_local_akaunting {
  188. akaunting_path="/var/www/${AKAUNTING_DOMAIN_NAME}/htdocs"
  189. if [ -d "$akaunting_path" ]; then
  190. suspend_site "${AKAUNTING_DOMAIN_NAME}"
  191. function_check backup_database_to_usb
  192. backup_database_to_usb akaunting
  193. backup_directory_to_usb "$akaunting_path" akaunting
  194. restart_site
  195. fi
  196. }
  197. function restore_local_akaunting {
  198. temp_restore_dir=/root/tempakaunting
  199. akaunting_dir="/var/www/${AKAUNTING_DOMAIN_NAME}/htdocs"
  200. suspend_site "${AKAUNTING_DOMAIN_NAME}"
  201. function_check akaunting_create_database
  202. akaunting_create_database
  203. restore_database akaunting "${AKAUNTING_DOMAIN_NAME}"
  204. chown www-data:www-data "$akaunting_dir"
  205. restart_site
  206. }
  207. function backup_remote_akaunting {
  208. akaunting_path="/var/www/${AKAUNTING_DOMAIN_NAME}/htdocs"
  209. if [ -d "$akaunting_path" ]; then
  210. suspend_site "${AKAUNTING_DOMAIN_NAME}"
  211. function_check backup_database_to_friend
  212. backup_database_to_friend akaunting
  213. backup_directory_to_friend "$akaunting_path" akaunting
  214. restart_site
  215. fi
  216. }
  217. function restore_remote_akaunting {
  218. akaunting_dir="/var/www/${AKAUNTING_DOMAIN_NAME}/htdocs"
  219. suspend_site "${AKAUNTING_DOMAIN_NAME}"
  220. function_check akaunting_create_database
  221. akaunting_create_database
  222. restore_database_from_friend akaunting "${AKAUNTING_DOMAIN_NAME}"
  223. chown www-data:www-data "$akaunting_dir"
  224. restart_site
  225. }
  226. function remove_akaunting {
  227. if [ ${#AKAUNTING_DOMAIN_NAME} -eq 0 ]; then
  228. return
  229. fi
  230. read_config_param "AKAUNTING_DOMAIN_NAME"
  231. read_config_param "MY_USERNAME"
  232. echo "Removing $AKAUNTING_DOMAIN_NAME"
  233. nginx_dissite "$AKAUNTING_DOMAIN_NAME"
  234. remove_certs "$AKAUNTING_DOMAIN_NAME"
  235. if [ -d "/var/www/$AKAUNTING_DOMAIN_NAME" ]; then
  236. rm -rf "/var/www/$AKAUNTING_DOMAIN_NAME"
  237. fi
  238. if [ -f "/etc/nginx/sites-available/$AKAUNTING_DOMAIN_NAME" ]; then
  239. rm "/etc/nginx/sites-available/$AKAUNTING_DOMAIN_NAME"
  240. fi
  241. function_check drop_database
  242. drop_database akaunting
  243. function_check remove_onion_service
  244. remove_onion_service akaunting "${AKAUNTING_ONION_PORT}"
  245. if grep -q "akaunting" /etc/crontab; then
  246. sed -i "/akaunting/d" /etc/crontab
  247. fi
  248. remove_app akaunting
  249. remove_completion_param install_akaunting
  250. sed -i '/akaunting/d' "$COMPLETION_FILE"
  251. function_check remove_ddns_domain
  252. remove_ddns_domain "$AKAUNTING_DOMAIN_NAME"
  253. }
  254. function install_akaunting {
  255. if [ ! $ONION_ONLY ]; then
  256. ONION_ONLY='no'
  257. fi
  258. if [ ! "$AKAUNTING_DOMAIN_NAME" ]; then
  259. echo $'No domain name was given for akaunting'
  260. exit 89353
  261. fi
  262. function_check install_mariadb
  263. install_mariadb
  264. function_check get_mariadb_password
  265. get_mariadb_password
  266. apt-get -yq install php-gettext php-curl php-gd php-mysql git curl
  267. apt-get -yq install memcached php-memcached php-intl exiftool libfcgi0ldbl
  268. if [ ! -d "/var/www/$AKAUNTING_DOMAIN_NAME" ]; then
  269. mkdir "/var/www/$AKAUNTING_DOMAIN_NAME"
  270. fi
  271. if [ ! -d "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" ]; then
  272. if [ -d /repos/akaunting ]; then
  273. mkdir "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs"
  274. cp -r -p /repos/akaunting/. "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs"
  275. cd "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" || exit 23458735
  276. git pull
  277. else
  278. function_check git_clone
  279. git_clone "$AKAUNTING_REPO" "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs"
  280. fi
  281. if [ ! -d "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" ]; then
  282. echo $'Unable to clone akaunting repo'
  283. exit 2589389
  284. fi
  285. fi
  286. cd "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" || exit 23468724527
  287. git checkout "$AKAUNTING_COMMIT" -b "$AKAUNTING_COMMIT"
  288. set_completion_param "akaunting commit" "$AKAUNTING_COMMIT"
  289. chmod g+w "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs"
  290. chown -R www-data:www-data "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs"
  291. cd "/var/www/$AKAUNTING_DOMAIN_NAME/htdocs" || exit 34783524
  292. install_composer
  293. function_check akaunting_create_database
  294. akaunting_create_database
  295. function_check add_ddns_domain
  296. add_ddns_domain "$AKAUNTING_DOMAIN_NAME"
  297. AKAUNTING_ONION_HOSTNAME=$(add_onion_service akaunting 80 ${AKAUNTING_ONION_PORT})
  298. akaunting_nginx_site=/etc/nginx/sites-available/$AKAUNTING_DOMAIN_NAME
  299. if [[ $ONION_ONLY == "no" ]]; then
  300. function_check nginx_http_redirect
  301. nginx_http_redirect "$AKAUNTING_DOMAIN_NAME" "index index.php"
  302. { echo 'server {';
  303. echo ' listen 443 ssl;';
  304. echo ' #listen [::]:443 ssl;';
  305. echo " server_name $AKAUNTING_DOMAIN_NAME;";
  306. echo ''; } >> "$akaunting_nginx_site"
  307. function_check nginx_compress
  308. nginx_compress "$AKAUNTING_DOMAIN_NAME"
  309. echo '' >> "$akaunting_nginx_site"
  310. echo ' # Security' >> "$akaunting_nginx_site"
  311. function_check nginx_ssl
  312. nginx_ssl "$AKAUNTING_DOMAIN_NAME"
  313. function_check nginx_security_options
  314. nginx_security_options "$AKAUNTING_DOMAIN_NAME"
  315. { echo ' add_header Strict-Transport-Security max-age=15768000;';
  316. echo '';
  317. echo ' access_log /dev/null;';
  318. echo ' error_log /dev/null;';
  319. echo '';
  320. echo " root /var/www/$AKAUNTING_DOMAIN_NAME/htdocs;";
  321. echo '';
  322. echo ' index index.php;';
  323. echo '';
  324. echo ' location ~ \.php {';
  325. echo ' include snippets/fastcgi-php.conf;';
  326. echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;';
  327. echo ' fastcgi_read_timeout 30;';
  328. echo ' }';
  329. echo '';
  330. echo ' location / {'; } >> "$akaunting_nginx_site"
  331. function_check nginx_limits
  332. nginx_limits "$AKAUNTING_DOMAIN_NAME" '15m'
  333. { echo " try_files \$uri \$uri/ @akaunting;";
  334. echo ' }';
  335. echo '';
  336. echo ' location @akaunting {';
  337. echo " rewrite ^(.*)\$ /index.php?p=\$1 last;";
  338. echo ' }';
  339. echo '';
  340. echo ' location ~ /\.(ht|git) {';
  341. echo ' deny all;';
  342. echo ' }';
  343. echo '';
  344. echo '}'; } >> "$akaunting_nginx_site"
  345. else
  346. echo -n '' > "$akaunting_nginx_site"
  347. fi
  348. { echo 'server {';
  349. echo " listen 127.0.0.1:$AKAUNTING_ONION_PORT default_server;";
  350. echo " server_name $AKAUNTING_ONION_HOSTNAME;";
  351. echo ''; } >> "$akaunting_nginx_site"
  352. function_check nginx_compress
  353. nginx_compress "$AKAUNTING_DOMAIN_NAME"
  354. echo '' >> "$akaunting_nginx_site"
  355. function_check nginx_security_options
  356. nginx_security_options "$AKAUNTING_DOMAIN_NAME"
  357. { echo '';
  358. echo ' access_log /dev/null;';
  359. echo ' error_log /dev/null;';
  360. echo '';
  361. echo " root /var/www/$AKAUNTING_DOMAIN_NAME/htdocs;";
  362. echo '';
  363. echo ' index index.php;';
  364. echo '';
  365. echo ' location ~ \.php {';
  366. echo ' include snippets/fastcgi-php.conf;';
  367. echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;';
  368. echo ' fastcgi_read_timeout 30;';
  369. echo ' }';
  370. echo '';
  371. echo ' location / {'; } >> "$akaunting_nginx_site"
  372. function_check nginx_limits
  373. nginx_limits "$AKAUNTING_DOMAIN_NAME" '15m'
  374. { echo " try_files \$uri \$uri/ @akaunting;";
  375. echo ' }';
  376. echo '';
  377. echo ' location @akaunting {';
  378. echo " rewrite ^(.*)\$ /index.php?p=\$1 last;";
  379. echo ' }';
  380. echo '';
  381. echo ' location ~ /\.(ht|git) {';
  382. echo ' deny all;';
  383. echo ' }';
  384. echo '}'; } >> "$akaunting_nginx_site"
  385. function_check configure_php
  386. configure_php
  387. function_check create_site_certificate
  388. create_site_certificate "$AKAUNTING_DOMAIN_NAME" 'yes'
  389. function_check nginx_ensite
  390. nginx_ensite "$AKAUNTING_DOMAIN_NAME"
  391. akaunting_remove_bad_links
  392. systemctl restart mariadb
  393. systemctl restart php7.0-fpm
  394. systemctl restart nginx
  395. "${PROJECT_NAME}-pass" -u "$MY_USERNAME" -a akaunting -p "$AKAUNTING_ADMIN_PASSWORD"
  396. set_completion_param "akaunting domain" "$AKAUNTING_DOMAIN_NAME"
  397. APP_INSTALLED=1
  398. }
  399. # NOTE: deliberately there is no "exit 0"