Pleroma + :whale: = :heart:
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.

pleroma 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. #!/bin/bash
  2. #########################################################
  3. # Options #
  4. #########################################################
  5. set -e
  6. set -o pipefail
  7. #########################################################
  8. # Globals #
  9. #########################################################
  10. readonly GITLAB_URI="https://git.pleroma.social"
  11. readonly PREFIX_API="api/v4/projects/pleroma%2Fpleroma/repository"
  12. readonly ENDPOINT_REPO="pleroma/pleroma.git"
  13. readonly ENDPOINT_FILE="pleroma/pleroma/raw"
  14. readonly ENDPOINT_LIST="pleroma/pleroma/files"
  15. readonly ENDPOINT_TAG="$PREFIX_API/tags"
  16. readonly ENDPOINT_BLOB="$PREFIX_API/blobs"
  17. readonly ENDPOINT_BRANCH="$PREFIX_API/branches"
  18. flags=""
  19. #########################################################
  20. # Helpers #
  21. #########################################################
  22. has_command() {
  23. if command -v 1>/dev/null 2>&1 "$1"; then
  24. return 0
  25. else
  26. return 1
  27. fi
  28. }
  29. require_command() {
  30. if ! has_command "$1"; then
  31. printf "\nError: This action requires the command '%s' in your PATH.\n" "$1"
  32. exit 1
  33. fi
  34. }
  35. require_file() {
  36. if [[ ! -f $1 ]]; then
  37. echo "File missing: '$1' (Example at: '$2')"
  38. FILE_FAILED=1
  39. fi
  40. }
  41. throw_file_errors() {
  42. if [[ -n "$FILE_FAILED" ]]; then
  43. echo ""
  44. echo "Please create the missing files first."
  45. echo "The script will now exit."
  46. exit 1
  47. fi
  48. }
  49. render_template() {
  50. require_command m4
  51. require_command awk
  52. m4 $flags docker-compose.m4 | awk 'NF'
  53. }
  54. docker_compose() {
  55. require_command docker-compose
  56. docker-compose \
  57. -f <(render_template) \
  58. --project-directory . \
  59. "$@"
  60. }
  61. load_env() {
  62. while read -r line; do
  63. if [[ "$line" == \#* ]] || [[ -z "$line" ]]; then
  64. continue;
  65. fi
  66. export "${line?}"
  67. flags="-D__${line?} $flags"
  68. done < .env
  69. }
  70. download_file() { # $1: source, $2: target
  71. if has_command curl; then
  72. curl -sSL "$1" -o "$2"
  73. elif has_command wget; then
  74. wget "$1" -O "$2"
  75. else
  76. printf "\nError: This action requires either curl or wget in your PATH.\n"
  77. exit 1
  78. fi
  79. }
  80. request_file_content() { # $1: source
  81. if has_command curl; then
  82. curl -sSL "$1"
  83. elif has_command wget; then
  84. wget "$1" -O- 2>/dev/null
  85. else
  86. printf "\nError: This action requires either curl or wget in your PATH.\n"
  87. exit 1
  88. fi
  89. }
  90. #########################################################
  91. # Subcommands #
  92. #########################################################
  93. action__build() {
  94. local cacheTag=""
  95. # Alternative 1: Get tags or branches from git (if installed)
  96. if [[ -z "$cacheTag" ]] && has_command git && has_command grep && has_command awk; then
  97. set +o pipefail
  98. local resolvedHash
  99. resolvedHash="$(git ls-remote $GITLAB_URI/$ENDPOINT_REPO | grep "/$PLEROMA_VERSION" | awk '{ print $1 }')"
  100. set -o pipefail
  101. if [[ -n "$resolvedHash" ]]; then
  102. cacheTag="$resolvedHash"
  103. fi
  104. fi
  105. # Alternative 2: Current time
  106. if [[ -z "$cacheTag" ]] && has_command date; then
  107. echo ""
  108. echo "WARNING WARNING WARNING"
  109. echo ""
  110. echo "You don't have git installed, so we cannot know if the cache is up to date."
  111. echo "We'll use the current unix timestamp as a replacement value,"
  112. echo "but this means that your cache is always 'stale' and docker wastes your time."
  113. echo ""
  114. echo "WARNING WARNING WARNING"
  115. echo ""
  116. echo "Waiting 5 seconds to make sure you notice this..."
  117. sleep 5
  118. cacheTag="$(date '+%s')"
  119. fi
  120. # Alternative 3: Random number with awk
  121. if [[ -z "$cacheTag" ]] && [[ -n "$RANDOM" ]]; then
  122. echo ""
  123. echo "WARNING WARNING WARNING"
  124. echo ""
  125. echo "You don't have git installed, so we cannot know if the cache is up to date."
  126. echo "Additionally you don't have \`date\` available. (What kind of pc is this?!)"
  127. echo "This means we cannot set any unique value as cache tag."
  128. echo ""
  129. echo "We'll generate a random number to try and mark the cache as 'always stale'."
  130. echo "Hoewever: Depending on your shell this might not always work, or only work a few times."
  131. echo ""
  132. echo "You should *really* get this fixed unless you know what you're doing."
  133. echo ""
  134. echo "WARNING WARNING WARNING"
  135. echo ""
  136. echo "Waiting 5 seconds to make sure you notice this..."
  137. sleep 5
  138. cacheTag="$RANDOM"
  139. fi
  140. # Last resort: Constant value
  141. if [[ -z "$cacheTag" ]]; then
  142. echo ""
  143. echo "WARNING WARNING WARNING"
  144. echo ""
  145. echo "You don't have git installed, so we cannot know if the cache is up to date."
  146. echo "Additionally you don't have \`date\` available, and your shell refuses to generate random numbers."
  147. echo "This means we cannot set any unique or random value as cache tag."
  148. echo "Consequently your cache will always be 'fresh' and you never get updates."
  149. echo ""
  150. echo "You can work around this by running \`docker system prune\` to throw away the build cache,"
  151. echo "but you should *really* get this fixed unless you know what you're doing."
  152. echo ""
  153. echo "WARNING WARNING WARNING"
  154. echo ""
  155. echo "Waiting 5 seconds to make sure you notice this..."
  156. sleep 5
  157. cacheTag="broken-host-env"
  158. fi
  159. echo -e "#> (Re-)Building with cache tag \`${cacheTag}\`...\n"
  160. docker_compose build --build-arg __CACHE_TAG="$cacheTag" server
  161. }
  162. action__dump() {
  163. cat <(render_template)
  164. }
  165. action__enter() {
  166. docker_compose exec server sh -c 'cd ~/pleroma && bash'
  167. }
  168. action__logs() {
  169. docker_compose logs "$@"
  170. }
  171. action__mix() {
  172. docker_compose exec server sh -c "cd ~/pleroma && mix $*"
  173. }
  174. action__passthrough() {
  175. docker_compose "$@"
  176. }
  177. action__p() {
  178. action__passthrough "$@"
  179. }
  180. action__restart() {
  181. action__stop
  182. action__start
  183. }
  184. action__start() {
  185. docker_compose up --remove-orphans -d
  186. }
  187. action__up() {
  188. action__start
  189. }
  190. action__stop() {
  191. docker_compose down
  192. }
  193. action__down() {
  194. action__stop
  195. }
  196. action__status() {
  197. docker_compose ps
  198. }
  199. action__ps() {
  200. action__status
  201. }
  202. action__debug() {
  203. require_command xhost
  204. local debug_mounts
  205. debug_mounts="
  206. -v $(pwd)/custom.d:/custom.d \
  207. -v $(pwd)/debug.d/build:/home/pleroma/pleroma/_build \
  208. -v $(pwd)/debug.d/deps:/home/pleroma/pleroma/deps \
  209. "
  210. if [[ ! -d ./debug.d ]]; then
  211. mkdir -p ./debug.d/{build,deps}
  212. fi
  213. if [[ ! -d ./custom.d/lib ]]; then
  214. mkdir -p ./custom.d/lib
  215. fi
  216. action__stop
  217. docker_compose run --rm -u pleroma -w /home/pleroma/pleroma "$debug_mounts" server bash -c 'cp -rvf /custom.d/* /home/pleroma/pleroma && mix deps.get'
  218. local x_flags=""
  219. if [[ $NO_X_FORWARDING != 1 ]]; then
  220. x_flags="-e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix"
  221. fi
  222. [[ $NO_X_FORWARDING == 1 ]] || xhost +local:root
  223. docker_compose run --rm -u pleroma -w /home/pleroma/pleroma "$debug_mounts" "$x_flags" server bash -c "cp -rvf /custom.d/* /home/pleroma/pleroma && $*"
  224. [[ $NO_X_FORWARDING == 1 ]] || xhost -local:root
  225. }
  226. action__mod() {
  227. require_command dialog
  228. require_command jq
  229. require_command curl
  230. if [[ ! -d ./debug.d ]]; then
  231. mkdir ./debug.d
  232. fi
  233. if [[ ! -f ./debug.d/mod_files.json ]] || [[ -n "$(find ./debug.d/mod_files.json -mmin +5)" ]]; then
  234. curl -sSL -# "$GITLAB_URI/$ENDPOINT_LIST/$PLEROMA_VERSION?format=json" > ./debug.d/mod_files.json
  235. if [[ -f ./debug.d/mod_files.lst ]]; then
  236. rm ./debug.d/mod_files.lst
  237. fi
  238. jq -r 'map("\(.)\n") | add' <./debug.d/mod_files.json >./debug.d/mod_files.lst
  239. fi
  240. if [[ -f ./debug.d/mod_files.lst ]] && [[ -r ./debug.d/mod_files.lst ]]; then
  241. choices=""
  242. while read -r candidate; do
  243. choices="$choices $candidate $(echo "$candidate" | rev | cut -d/ -f1 | rev)"
  244. done <<< "$(grep -E ".*$1.*" <./debug.d/mod_files.lst)"
  245. res=$(mktemp)
  246. dialog --menu "Select the file you want to modify:" 35 80 30 $choices 2>"$res"
  247. choice=$(cat "$res")
  248. install -D <(echo '') "./custom.d/$choice"
  249. curl -sSL -# "$GITLAB_URI/$ENDPOINT_FILE/$PLEROMA_VERSION/$choice" > "./custom.d/$choice"
  250. else
  251. install -D <(echo '') "./custom.d/$1"
  252. curl -sSL -# "$GITLAB_URI/$ENDPOINT_FILE/$PLEROMA_VERSION/$1" > "./custom.d/$1"
  253. fi
  254. }
  255. action__cp() {
  256. container="$(docker_compose ps -q server)"
  257. echo "$container:$1 -> $2"
  258. docker cp "$container:$1" "$2"
  259. }
  260. #########################################################
  261. # Help #
  262. #########################################################
  263. print_help() {
  264. echo "
  265. Pleroma Maintenance Script
  266. Usage:
  267. $0 [action] [action-args...]
  268. Actions:
  269. build (Re)build the pleroma container.
  270. dump Dump the generated docker-compose.yml to stdout.
  271. debug [bin] [args...] Launches a new pleroma container but uses \$bin instead of phx.server as entrypoint.
  272. **Warning**: This is intended for debugging pleroma with tools like :debugger and :observer.
  273. It thus forwards your X-Server into docker and temporarily fiddles with your xhost
  274. access controls. If this is a security concern for you, please export NO_X_FORWARDING=1
  275. before launching a debugger session.
  276. enter Spawn a shell inside the container for debugging/maintenance.
  277. This command does not link to the postgres container.
  278. If you need that use #debug instead.
  279. logs Show the current container logs.
  280. mix [task] [args...] Run a mix task without entering the container.
  281. mod [file] Creates the file in custom.d and downloads the content from pleroma.social.
  282. The download respects your \$PLEROMA_VERSION from .env.
  283. passthrough / p [...] Pass any custom command to docker-compose.
  284. restart Executes #stop and #start respectively.
  285. start / up Start pleroma and sibling services.
  286. stop / down Stop pleroma and sibling services.
  287. status / ps Show the current container status.
  288. copy / cp [source] [target] Copy a file from your pc to the pleroma container.
  289. This operation only works in one direction.
  290. For making permanent changes to the container use custom.d.
  291. Environment:
  292. DEBUG can be used to modify the loglevel.
  293. DEBUG=1 prints all commands before they are executed.
  294. DEBUG=2 prints all bash statements before they are executed (a lot).
  295. SHOPT can be used to modify shell options.
  296. Pass a list of options to this variable like SHOPT='-x -e'.
  297. For setting long options with -o use a colon (:) instead of a space
  298. to seperate the option from -o. For example: SHOPT='-x -e -o:pipefail'.
  299. Contributing:
  300. You can report bugs or contribute to this project at:
  301. https://glitch.sh/sn0w/pleroma-docker
  302. "
  303. }
  304. #########################################################
  305. # Main #
  306. #########################################################
  307. # Check if there is any command at all
  308. if [[ -z "$1" ]]; then
  309. print_help
  310. exit 1
  311. fi
  312. # Check for SHOPTs
  313. if [[ -n "$SHOPT" ]]; then
  314. for opt in $SHOPT; do
  315. if [[ $opt =~ ":" ]]; then
  316. set -o "${opt//-o:/}"
  317. else
  318. set "$opt"
  319. fi
  320. done
  321. fi
  322. # Check for DEBUG
  323. if [[ -n "$DEBUG" ]]; then
  324. if [[ $DEBUG == 1 ]]; then
  325. export DEBUG_COMMANDS=1
  326. elif [[ $DEBUG == 2 ]]; then
  327. set -x
  328. fi
  329. fi
  330. # Check if the option is "help"
  331. case "$1" in
  332. "help"|"h"|"--help"|"-h"|"-?")
  333. print_help
  334. exit 0
  335. ;;
  336. esac
  337. # Check if the called command exists
  338. func="action__${1}"
  339. if ! type -t "$func" 1>/dev/null 2>&1; then
  340. echo "Unknown flag or subcommand."
  341. echo "Try '$0 help'"
  342. exit 1
  343. fi
  344. # Fail if mandatory files are missing
  345. require_file ".env" ".env.dist"
  346. require_file "config.exs" "config.dist.exs"
  347. throw_file_errors
  348. # Parse .env
  349. load_env
  350. # Handle DEBUG=2
  351. [[ $DEBUG != 1 ]] || set -x
  352. # Jump to called function
  353. shift
  354. $func "$@"
  355. # Disable debug mode
  356. { [[ $DEBUG != 1 ]] || set +x; } 2>/dev/null