freedombone-app-scuttlebot 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #!/bin/bash
  2. #
  3. # .---. . .
  4. # | | |
  5. # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
  6. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
  7. # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
  8. #
  9. # Freedom in the Cloud
  10. #
  11. # scuttlebot pub application. Enables nat traversal for SSB.
  12. # https://scuttlebot.io
  13. #
  14. # License
  15. # =======
  16. #
  17. # Copyright (C) 2017-2018 Bob Mottram <bob@freedombone.net>
  18. #
  19. # This program is free software: you can redistribute it and/or modify
  20. # it under the terms of the GNU Affero General Public License as published by
  21. # the Free Software Foundation, either version 3 of the License, or
  22. # (at your option) any later version.
  23. #
  24. # This program is distributed in the hope that it will be useful,
  25. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. # GNU Affero General Public License for more details.
  28. #
  29. # You should have received a copy of the GNU Affero General Public License
  30. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  31. VARIANTS='full full-vim social'
  32. IN_DEFAULT_INSTALL=0
  33. SHOW_ON_ABOUT=0
  34. SHOW_ICANN_ADDRESS_ON_ABOUT=0
  35. SCUTTLEBOT_DOMAIN_NAME=
  36. SCUTTLEBOT_CODE=
  37. SCUTTLEBOT_VERSION='10.4.6'
  38. SCUTTLEBOT_PORT=8010
  39. SCUTTLEBOT_ONION_PORT=8623
  40. GIT_SSB_PORT=7718
  41. NGINX_GIT_SSB_PORT=7719
  42. scuttlebot_variables=(MY_USERNAME
  43. SCUTTLEBOT_DOMAIN_NAME
  44. SCUTTLEBOT_CODE
  45. DEFAULT_DOMAIN_NAME
  46. SYSTEM_TYPE)
  47. function logging_on_scuttlebot {
  48. echo -n ''
  49. }
  50. function logging_off_scuttlebot {
  51. echo -n ''
  52. }
  53. function scuttlebot_create_invite {
  54. invite_string=$(su -c "sbot invite.create 1" - scuttlebot | sed 's/"//g')
  55. clear
  56. echo -e "\\n\\nYour Scuttlebot invite code is:\\n\\n${invite_string}\\n\\n"
  57. # shellcheck disable=SC2034
  58. read -n1 -r -p $"Press any key to continue..." key
  59. }
  60. function configure_interactive_scuttlebot {
  61. while true
  62. do
  63. data=$(mktemp 2>/dev/null)
  64. dialog --backtitle $"Freedombone Control Panel" \
  65. --title $"Scuttlebot" \
  66. --radiolist $"Choose an operation:" 10 50 2 \
  67. 1 $"Create an invite" off \
  68. 2 $"Exit" on 2> "$data"
  69. sel=$?
  70. case $sel in
  71. 1) rm -f "$data"
  72. return;;
  73. 255) rm -f "$data"
  74. return;;
  75. esac
  76. case $(cat "$data") in
  77. 1) scuttlebot_create_invite;;
  78. 2) rm -f "$data"
  79. break;;
  80. esac
  81. rm -f "$data"
  82. done
  83. }
  84. function remove_user_scuttlebot {
  85. echo -n ''
  86. # remove_username="$1"
  87. }
  88. function add_user_scuttlebot {
  89. # new_username="$1"
  90. # new_user_password="$2"
  91. echo '0'
  92. }
  93. function install_interactive_scuttlebot {
  94. if [[ $ONION_ONLY != "no" ]]; then
  95. SCUTTLEBOT_DOMAIN_NAME='scuttlebot.local'
  96. write_config_param "SCUTTLEBOT_DOMAIN_NAME" "$SCUTTLEBOT_DOMAIN_NAME"
  97. else
  98. function_check interactive_site_details
  99. interactive_site_details scuttlebot
  100. fi
  101. APP_INSTALLED=1
  102. }
  103. function change_password_scuttlebot {
  104. # new_username="$1"
  105. # new_user_password="$2"
  106. echo '0'
  107. }
  108. function reconfigure_scuttlebot {
  109. if [ -d /etc/scuttlebot/.ssb ]; then
  110. systemctl stop scuttlebot
  111. rm -rf /etc/scuttlebot/.ssb
  112. systemctl start scuttlebot
  113. fi
  114. }
  115. function upgrade_scuttlebot {
  116. if ! grep -q 'scuttlebot version:' $"COMPLETION_FILE"; then
  117. return
  118. fi
  119. CURR_SCUTTLEBOT_VERSION=$(get_completion_param "scuttlebot version")
  120. echo "scuttlebot current version: ${CURR_SCUTTLEBOT_VERSION}"
  121. echo "scuttlebot app version: ${SCUTTLEBOT_VERSION}"
  122. if [[ "${CURR_SCUTTLEBOT_VERSION}" == "${SCUTTLEBOT_VERSION}" ]]; then
  123. return
  124. fi
  125. if ! npm upgrade -g scuttlebot@${SCUTTLEBOT_VERSION} --save; then
  126. return
  127. fi
  128. sed -i "s|scuttlebot version.*|scuttlebot version:${SCUTTLEBOT_VERSION}|g" "${COMPLETION_FILE}"
  129. }
  130. function backup_local_scuttlebot {
  131. if [ -d /etc/scuttlebot/.ssb ]; then
  132. systemctl stop scuttlebot
  133. function_check backup_directory_to_usb
  134. backup_directory_to_usb /etc/scuttlebot/.ssb scuttlebot
  135. systemctl start scuttlebot
  136. fi
  137. }
  138. function restore_local_scuttlebot {
  139. if [ -d /etc/scuttlebot ]; then
  140. systemctl stop scuttlebot
  141. temp_restore_dir=/root/tempscuttlebot
  142. function_check restore_directory_from_usb
  143. restore_directory_from_usb $temp_restore_dir scuttlebot
  144. if [ -d $temp_restore_dir/etc/scuttlebot/.ssb ]; then
  145. cp -r $temp_restore_dir/etc/scuttlebot/.ssb /etc/scuttlebot/
  146. else
  147. cp -r $temp_restore_dir/* /etc/scuttlebot/.ssb/*
  148. fi
  149. systemctl start scuttlebot
  150. rm -rf $temp_restore_dir
  151. fi
  152. }
  153. function backup_remote_scuttlebot {
  154. if [ -d /etc/scuttlebot/.ssb ]; then
  155. systemctl stop scuttlebot
  156. function_check backup_directory_to_friend
  157. backup_directory_to_friend /etc/scuttlebot/.ssb scuttlebot
  158. systemctl start scuttlebot
  159. fi
  160. }
  161. function restore_remote_scuttlebot {
  162. if [ -d /etc/scuttlebot ]; then
  163. systemctl stop scuttlebot
  164. temp_restore_dir=/root/tempscuttlebot
  165. function_check restore_directory_from_friend
  166. restore_directory_from_friend $temp_restore_dir scuttlebot
  167. if [ -d $temp_restore_dir/etc/scuttlebot/.ssb ]; then
  168. cp -r $temp_restore_dir/etc/scuttlebot/.ssb /etc/scuttlebot/
  169. else
  170. cp -r $temp_restore_dir/* /etc/scuttlebot/.ssb/*
  171. fi
  172. systemctl start scuttlebot
  173. rm -rf $temp_restore_dir
  174. fi
  175. }
  176. function remove_scuttlebot {
  177. firewall_remove ${SCUTTLEBOT_PORT}
  178. firewall_remove ${GIT_SSB_PORT}
  179. if [ $SCUTTLEBOT_DOMAIN_NAME ]; then
  180. nginx_dissite ${SCUTTLEBOT_DOMAIN_NAME}
  181. rm /etc/nginx/sites-available/${SCUTTLEBOT_DOMAIN_NAME}
  182. fi
  183. systemctl stop git_ssb
  184. systemctl stop scuttlebot
  185. systemctl disable git_ssb
  186. systemctl disable scuttlebot
  187. rm /etc/systemd/system/git_ssb.service
  188. rm /etc/systemd/system/scuttlebot.service
  189. systemctl daemon-reload
  190. userdel -r scuttlebot
  191. if [ -d /etc/scuttlebot ]; then
  192. rm -rf /etc/scuttlebot
  193. fi
  194. if [ -f /usr/bin/git-ssb-create ]; then
  195. rm /usr/bin/git-ssb-create
  196. fi
  197. remove_completion_param install_scuttlebot
  198. sed -i '/scuttlebot /d' "$COMPLETION_FILE"
  199. }
  200. function git_ssb_script {
  201. if [[ "$1" == "mesh" ]]; then
  202. # shellcheck disable=SC2154
  203. git_ssb_script_name=$rootdir/usr/bin/git-ssb-create
  204. git_ssb_daemon_filename=$rootdir/etc/systemd/system/git_ssb.service
  205. else
  206. git_ssb_script_name=/usr/bin/git-ssb-create
  207. git_ssb_daemon_filename=/etc/systemd/system/git_ssb.service
  208. fi
  209. { echo '#!/bin/bash';
  210. echo "reponame=\"\$1\"";
  211. echo '';
  212. echo "if [[ \"\$reponame\" != \"\" ]]; then";
  213. echo " mkdir \$reponame";
  214. echo " cd \$reponame";
  215. echo ' git init';
  216. echo " git ssb create ssb \$reponame";
  217. echo ' git push --tags ssb master';
  218. echo 'fi';
  219. echo 'exit 0'; } > $git_ssb_script_name
  220. chmod +x $git_ssb_script_name
  221. { echo '[Unit]';
  222. echo 'Description=Git SSB (SSB git web interface)';
  223. echo 'After=syslog.target';
  224. echo 'After=network.target';
  225. echo 'After=scuttlebot.target';
  226. echo '';
  227. echo '[Service]';
  228. echo 'Type=simple';
  229. echo 'User=scuttlebot';
  230. echo 'Group=scuttlebot';
  231. echo "WorkingDirectory=/etc/scuttlebot";
  232. echo "ExecStart=/usr/bin/git ssb web --public localhost:$GIT_SSB_PORT";
  233. echo 'Restart=always';
  234. echo 'Environment="USER=scuttlebot"';
  235. echo '';
  236. echo '[Install]';
  237. echo 'WantedBy=multi-user.target'; } > $git_ssb_daemon_filename
  238. }
  239. function scuttlebot_git_setup {
  240. if [[ "$1" == "mesh" ]]; then
  241. if [ ! -d "$rootdir/usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web/highlight" ]; then
  242. mkdir "$rootdir/usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web/highlight"
  243. fi
  244. if [ ! -f "$rootdir/usr/local/lib/node_modules/git-ssb/node_modules/highlight.js/styles/foundation.css" ]; then
  245. echo $'Could not find foundation.css'
  246. exit 347687245
  247. fi
  248. cp "$rootdir/usr/local/lib/node_modules/git-ssb/node_modules/highlight.js/styles/foundation.css" "$rootdir/usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web/highlight/foundation.css"
  249. git_ssb_nginx_site=$rootdir/etc/nginx/sites-available/git_ssb
  250. { echo 'server {';
  251. echo " listen $NGINX_GIT_SSB_PORT default_server;";
  252. echo " server_name P${PEER_ID}.local;";
  253. echo '';
  254. echo ' access_log /dev/null;';
  255. echo ' error_log /dev/null;';
  256. echo '';
  257. echo ' add_header X-XSS-Protection "1; mode=block";';
  258. echo ' add_header X-Content-Type-Options nosniff;';
  259. echo ' add_header X-Frame-Options SAMEORIGIN;'; } > "$git_ssb_nginx_site"
  260. else
  261. if [ ! $SCUTTLEBOT_DOMAIN_NAME ]; then
  262. exit 7357225
  263. fi
  264. if [ ! -d /usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web/highlight ]; then
  265. mkdir /usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web/highlight
  266. fi
  267. if [ ! -f /usr/local/lib/node_modules/git-ssb/node_modules/highlight.js/styles/foundation.css ]; then
  268. echo $'Could not find foundation.css'
  269. exit 347687245
  270. fi
  271. cp /usr/local/lib/node_modules/git-ssb/node_modules/highlight.js/styles/foundation.css /usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web/highlight/foundation.css
  272. git_ssb_nginx_site=/etc/nginx/sites-available/${SCUTTLEBOT_DOMAIN_NAME}
  273. function_check nginx_http_redirect
  274. nginx_http_redirect $SCUTTLEBOT_DOMAIN_NAME "index index.html"
  275. { echo 'server {';
  276. echo ' listen 443 ssl;';
  277. echo ' #listen [::]:443 ssl;';
  278. echo " server_name $SCUTTLEBOT_DOMAIN_NAME;";
  279. echo ''; } >> $git_ssb_nginx_site
  280. function_check nginx_compress
  281. nginx_compress $SCUTTLEBOT_DOMAIN_NAME
  282. echo '' >> "$git_ssb_nginx_site"
  283. echo ' # Security' >> "$git_ssb_nginx_site"
  284. function_check nginx_ssl
  285. nginx_ssl $SCUTTLEBOT_DOMAIN_NAME
  286. function_check nginx_disable_sniffing
  287. nginx_disable_sniffing $SCUTTLEBOT_DOMAIN_NAME
  288. fi
  289. { echo '';
  290. echo ' root /usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web;';
  291. echo '';
  292. echo ' location = / {';
  293. echo " proxy_pass http://localhost:${GIT_SSB_PORT};";
  294. echo " proxy_set_header X-Real-IP \$remote_addr;";
  295. echo " proxy_set_header Host \$host;";
  296. echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;";
  297. echo ' proxy_http_version 1.1;';
  298. echo " proxy_set_header Upgrade \$http_upgrade;";
  299. echo ' proxy_set_header Connection upgrade;';
  300. echo ' }';
  301. echo '}'; } >> $git_ssb_nginx_site
  302. if [ "$SCUTTLEBOT_ONION_HOSTNAME" ]; then
  303. { echo '';
  304. echo 'server {';
  305. echo " listen 127.0.0.1:${SCUTTLEBOT_ONION_PORT} default_server;";
  306. echo " server_name ${SCUTTLEBOT_ONION_HOSTNAME};";
  307. echo '';
  308. echo ' access_log /dev/null;';
  309. echo ' error_log /dev/null;';
  310. echo '';
  311. echo ' add_header X-XSS-Protection "1; mode=block";';
  312. echo ' add_header X-Content-Type-Options nosniff;';
  313. echo ' add_header X-Frame-Options SAMEORIGIN;';
  314. echo '';
  315. echo ' root /usr/local/lib/node_modules/git-ssb/node_modules/git-ssb-web;';
  316. echo '';
  317. echo ' location = / {';
  318. echo " proxy_pass http://localhost:${GIT_SSB_PORT};";
  319. echo " proxy_set_header X-Real-IP \$remote_addr;";
  320. echo " proxy_set_header Host \$host;";
  321. echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;";
  322. echo ' proxy_http_version 1.1;';
  323. echo " proxy_set_header Upgrade \$http_upgrade;";
  324. echo ' proxy_set_header Connection upgrade;';
  325. echo ' }';
  326. echo '}'; } >> $git_ssb_nginx_site
  327. fi
  328. if [[ "$1" != "mesh" ]]; then
  329. nginx_ensite git_ssb
  330. fi
  331. }
  332. function mesh_install_dat {
  333. get_npm_arch
  334. cat <<EOF > "$rootdir/usr/bin/install_dat"
  335. #!/bin/bash
  336. npm install --arch=$NPM_ARCH -g dat
  337. npm install --arch=$NPM_ARCH -g @garbados/dat-boi
  338. npm install --arch=$NPM_ARCH -g add-to-systemd
  339. add-to-systemd dat-boi --user "$(whoami)" "$(which dat-boi)"
  340. EOF
  341. chroot "$rootdir" /bin/chmod +x /usr/bin/install_dat
  342. chroot "$rootdir" /usr/bin/install_dat
  343. rm "$rootdir/usr/bin/install_dat"
  344. }
  345. function install_dat {
  346. npm install -g dat
  347. npm install -g @garbados/dat-boi
  348. npm install -g add-to-systemd
  349. add-to-systemd dat-boi --user "$(whoami)" "$(which dat-boi)"
  350. }
  351. function mesh_install_scuttlebot {
  352. SCUTTLEBOT_ONION_HOSTNAME=
  353. mesh_install_dat
  354. get_npm_arch
  355. cat <<EOF > "$rootdir/usr/bin/install_scuttlebot"
  356. #!/bin/bash
  357. npm install --arch=$NPM_ARCH -g scuttlebot@${SCUTTLEBOT_VERSION}
  358. npm install --arch=$NPM_ARCH -g git-ssb
  359. npm install --arch=$NPM_ARCH -g git-remote-ssb
  360. EOF
  361. chroot "$rootdir" /bin/chmod +x /usr/bin/install_scuttlebot
  362. chroot "$rootdir" /usr/bin/install_scuttlebot
  363. rm "$rootdir/usr/bin/install_scuttlebot"
  364. if [ ! -f "$rootdir/usr/local/bin/sbot" ]; then
  365. echo $'Scuttlebot was not installed'
  366. exit 528253
  367. fi
  368. if [ ! -d "$rootdir/etc/scuttlebot" ]; then
  369. mkdir -p "$rootdir/etc/scuttlebot"
  370. fi
  371. # an unprivileged user to run as
  372. chroot "$rootdir" useradd -d /etc/scuttlebot/ scuttlebot
  373. # daemon
  374. { echo '[Unit]';
  375. echo 'Description=Scuttlebot (messaging system)';
  376. echo 'After=syslog.target';
  377. echo 'After=network.target';
  378. echo '';
  379. echo '[Service]';
  380. echo 'Type=simple';
  381. echo 'User=scuttlebot';
  382. echo 'Group=scuttlebot';
  383. echo "WorkingDirectory=/etc/scuttlebot";
  384. echo 'ExecStart=/usr/local/bin/sbot server';
  385. echo 'Restart=always';
  386. echo 'Environment="USER=scuttlebot"';
  387. echo '';
  388. echo '[Install]';
  389. echo 'WantedBy=multi-user.target'; } > "$rootdir/etc/systemd/system/scuttlebot.service"
  390. scuttlebot_git_setup mesh
  391. git_ssb_script mesh
  392. }
  393. function install_scuttlebot {
  394. function_check install_nodejs
  395. install_nodejs scuttlebot
  396. npm install -g scuttlebot@${SCUTTLEBOT_VERSION}
  397. if [ ! -f /usr/local/bin/sbot ]; then
  398. exit 528253
  399. fi
  400. install_dat
  401. npm install -g git-ssb
  402. npm install -g git-remote-ssb
  403. if [ ! -d /etc/scuttlebot ]; then
  404. mkdir -p /etc/scuttlebot
  405. fi
  406. # an unprivileged user to run as
  407. useradd -d /etc/scuttlebot/ scuttlebot
  408. # daemon
  409. { echo '[Unit]';
  410. echo 'Description=Scuttlebot (messaging system)';
  411. echo 'After=syslog.target';
  412. echo 'After=network.target';
  413. echo '';
  414. echo '[Service]';
  415. echo 'Type=simple';
  416. echo 'User=scuttlebot';
  417. echo 'Group=scuttlebot';
  418. echo "WorkingDirectory=/etc/scuttlebot";
  419. echo 'ExecStart=/usr/local/bin/sbot server';
  420. echo 'Restart=always';
  421. echo 'Environment="USER=scuttlebot"';
  422. echo '';
  423. echo '[Install]';
  424. echo 'WantedBy=multi-user.target'; } > /etc/systemd/system/scuttlebot.service
  425. chown -R scuttlebot:scuttlebot /etc/scuttlebot
  426. # files gw_name myhostname mdns4_minimal [NOTFOUND=return] dns
  427. sed -i "s|hosts:.*|hosts: files mdns4_minimal dns mdns4 mdns|g" /etc/nsswitch.conf
  428. # start the daemon
  429. systemctl enable scuttlebot.service
  430. systemctl daemon-reload
  431. systemctl start scuttlebot.service
  432. sleep 3
  433. if [ ! -d /etc/scuttlebot/.ssb ]; then
  434. echo $'Scuttlebot config not generated'
  435. exit 73528
  436. fi
  437. { echo '{';
  438. echo " \"host\": \"${DEFAULT_DOMAIN_NAME}\",";
  439. echo " \"port\": ${SCUTTLEBOT_PORT},";
  440. echo ' "timeout": 30000,';
  441. echo ' "pub": true,';
  442. echo ' "local": true,';
  443. echo ' "friends": {';
  444. echo ' "dunbar": 150,';
  445. echo ' "hops": 3';
  446. echo ' },';
  447. echo ' "gossip": {';
  448. echo ' "connections": 2';
  449. echo ' },';
  450. echo ' "master": [],';
  451. echo ' "logging": {';
  452. echo ' "level": "error"';
  453. echo ' }';
  454. echo '}'; } > /etc/scuttlebot/.ssb/config
  455. chown scuttlebot:scuttlebot /etc/scuttlebot/.ssb/config
  456. systemctl restart scuttlebot.service
  457. firewall_add scuttlebot ${SCUTTLEBOT_PORT}
  458. firewall_add git_ssb ${GIT_SSB_PORT}
  459. SCUTTLEBOT_ONION_HOSTNAME=$(add_onion_service scuttlebot 80 ${SCUTTLEBOT_ONION_PORT})
  460. scuttlebot_git_setup
  461. git_ssb_script
  462. systemctl enable git_ssb.service
  463. systemctl daemon-reload
  464. systemctl start git_ssb.service
  465. function_check create_site_certificate
  466. create_site_certificate ${SCUTTLEBOT_DOMAIN_NAME} 'yes'
  467. systemctl restart nginx
  468. if ! grep -q "scuttlebot version:" "${COMPLETION_FILE}"; then
  469. echo "scuttlebot version:${SCUTTLEBOT_VERSION}" >> "${COMPLETION_FILE}"
  470. else
  471. sed -i "s|scuttlebot version.*|scuttlebot version:${SCUTTLEBOT_VERSION}|g" "${COMPLETION_FILE}"
  472. fi
  473. APP_INSTALLED=1
  474. }
  475. # NOTE: deliberately no exit 0