diff --git a/.env.dist b/.env.dist index 51013f6..ea38c3c 100644 --- a/.env.dist +++ b/.env.dist @@ -1,18 +1,3 @@ -# -# Note: The values of this file that are passed directly to -# pleroma need type hints to be applied correctly. -# The implemented types are int, bool, and string. -# Typed variables look like this: KEY=type:VALUE. -# Not specifying a type implies a string. -# -# In general: Your instance should work as expected if you leave the types as they are. -# That is: don't remove them, don't add them, don't change them. -# Always just change the values. -# -# You don't need to escape colons in your strings. -# PLEROMA_NAME=string:std::pleroma::coolinstance will work as expected. -# - ######################### # Script settings # ######################### @@ -62,15 +47,12 @@ DOCKER_GID=1000 # Database settings # ########################### -# Leave POSTGRES_IP empty unless you plan to install your own database -# Leave the POSTGRES_DB, POSTGRES_USER and POSTGRES_PASSWORD as-is -# unless you use your own database. +# When you use the managed postgres container +# those will be the credentials the container is generated with. -POSTGRES_IP= POSTGRES_DB=pleroma POSTGRES_USER=pleroma POSTGRES_PASSWORD=pleroma -PLEROMA_DB_POOL_SIZE=int:16 ########################## # Pleroma Settings # @@ -82,50 +64,6 @@ MIX_ENV=prod # The git tag, revision, or branch to check out on build PLEROMA_VERSION=develop -# The loglevel to use -# (error/warn/info/debug) -PLEROMA_LOGLEVEL=error - -# The domain/scheme where pleroma will be hosted -# URL is a bare TLD -# SCHEME is the protocol without "://" -# PORT is the *external* port (ie that of your reverse proxy) +# Domain to run at (only relevant for traefik mode) PLEROMA_URL=coolsite.moe -PLEROMA_SCHEME=https -PLEROMA_PORT=int:443 - -# The seed for your secret keys -# (Enter something as random as possible) -# (On linux you can try something like "dd if=/dev/urandom bs=1 count=64 2>/dev/null | base64 -w 0 | rev | cut -b 2- | rev") -PLEROMA_SECRET_KEY_BASE= - -# The name of your instance -# (This is displayed in the top-left in pleroma-fe) -PLEROMA_NAME=string:coolInstance - -# Your contact info -PLEROMA_ADMIN_EMAIL=admin@coolsite.moe - -# How many chars a notice may have at max. -PLEROMA_MAX_NOTICE_CHARS=int:500 - -# Whether your instance accepts new users or not (true/false) -PLEROMA_REGISTRATIONS_OPEN=bool:true - -# Enable media proxy (true/false)? -PLEROMA_MEDIA_PROXY_ENABLED=bool:false - -# The url of your media proxy (if enabled) [with "http(s)://"] -PLEROMA_MEDIA_PROXY_URL=string:https://cdn.coolsite.moe - -# Redirect to source on cache fail? -PLEROMA_MEDIA_PROXY_REDIRECT_ON_FAILURE=bool:true - -# Whether to enable the chat feature or not -PLEROMA_CHAT_ENABLED=bool:true - -# Where to store uploads. -# This is only relevant inside the container. -# The host path is always $DOCKER_DATADIR/uploads. -# So, you probably don't need to change this. -PLEROMA_UPLOADS_PATH=/uploads +PLEROMA_MEDIA_PROXY_URL=cdn.coolsite.moe diff --git a/.gitignore b/.gitignore index aa4b1f7..4e5fca7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ data .env +config.yml custom.d/ !custom.d/.gitkeep docker-compose.yml +config.exs # Created by https://www.gitignore.io/api/osx,linux,windows diff --git a/Dockerfile b/Dockerfile index cbaabbd..5e2ba04 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,67 +1,60 @@ -FROM debian:9-slim +FROM alpine:3.8 -VOLUME /custom.d -EXPOSE 4000 - -ENV DEBIAN_FRONTEND=noninteractive +# Set up environment ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 +ENV MIX_ENV=prod -# Register pseudo-entrypoint -ADD ./entrypoint.sh / -RUN chmod a+x /entrypoint.sh -CMD ["/entrypoint.sh"] +# Prepare mounts +VOLUME /custom.d -# Set "real" entrypoint to an init system. -# TODO: Replace with --init when docker 18.06 is GA -ENV TINI_VERSION v0.18.0 -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini -RUN chmod +x /tini -ENTRYPOINT ["/tini", "--"] +# Expose default pleroma port to host +EXPOSE 4000 -# Get build dependencies +# Get dependencies RUN \ - apt-get update \ - && apt-get install -y --no-install-recommends apt-utils \ - && apt-get install -y --no-install-recommends git wget ca-certificates gnupg2 build-essential \ + apk add --no-cache --virtual .tools \ + git curl rsync postgresql-client \ \ - && wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb \ - && dpkg -i erlang-solutions_1.0_all.deb \ - && apt-get update \ - && apt-get install -y --no-install-recommends esl-erlang elixir \ + && apk add --no-cache --virtual .sdk \ + build-base \ \ - && rm -rf /var/lib/apt/lists/* + && apk add --no-cache --virtual .runtime \ + erlang erlang-runtime-tools erlang-xmerl elixir + +# Add entrypoint +COPY ./entrypoint.sh / +RUN chmod a+x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] # Limit permissions -ARG DOCKER_UID -ARG DOCKER_GID -ARG PLEROMA_UPLOADS_PATH +ARG DOCKER_UID=1000 +ARG DOCKER_GID=1000 +ARG PLEROMA_UPLOADS_PATH=/uploads RUN \ - groupadd --gid ${DOCKER_GID} pleroma \ - && useradd -m -s /bin/bash --gid ${DOCKER_GID} --uid ${DOCKER_UID} pleroma \ + addgroup --gid ${DOCKER_GID} pleroma \ + && adduser -S -s /bin/ash -G pleroma -u ${DOCKER_UID} pleroma \ && mkdir -p /custom.d $PLEROMA_UPLOADS_PATH \ && chown -R pleroma:pleroma /custom.d $PLEROMA_UPLOADS_PATH USER pleroma WORKDIR /home/pleroma -# Get pleroma +# Get pleroma sources RUN git clone --progress https://git.pleroma.social/pleroma/pleroma.git ./pleroma WORKDIR /home/pleroma/pleroma -# Get rebar/hex -RUN \ - mix local.hex --force \ - && mix local.rebar --force - -# Bust the build cache -ARG __BUST_CACHE -ENV __BUST_CACHE $__BUST_CACHE +# Bust the build cache (if needed) +# This works by setting an environment variable with the last +# used version/branch/tag/commitish/... which originates in the script. +# If the host doesn't have the required tool for "smart version detection" +# we'll just use the current timestamp here which forces a rebuild every time. +ARG __CACHE_TAG +ENV __CACHE_TAG $__CACHE_TAG # Fetch changes, checkout ARG PLEROMA_VERSION - RUN \ git fetch --all \ && git checkout $PLEROMA_VERSION \ @@ -69,12 +62,9 @@ RUN \ # Precompile RUN \ - mix deps.get \ - && mix compile + cp ./config/dev.exs ./config/prod.secret.exs \ + && BUILDTIME=1 /entrypoint.sh \ + && rm ./config/prod.secret.exs -# Insert overrides and config helper -COPY --chown=pleroma:pleroma ./docker-config.exs /docker-config.exs +# Insert overrides COPY --chown=pleroma:pleroma ./custom.d /home/pleroma/pleroma -RUN \ - ln -s /docker-config.exs config/prod.secret.exs \ - && ln -s /docker-config.exs config/dev.secret.exs diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bd3a56b --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2017-2018, sn0w +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 74e0ba4..5c46890 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,16 @@ This repository dockerizes it for easier deployment.
```cpp -#include -#include +#include /* * This repository comes with ABSOLUTELY NO WARRANTY * * I am not responsible for burning servers, angry users, fedi drama, - * thermonuclear war, or you getting fired because your boss saw your - * NSFW posts. Please do some research if you have any concerns about included - * features or the software used by this script before using it. + * thermonuclear war, or you getting fired because your boss saw your NSFW posts. + * Please do some research if you have any concerns about included + * features or the software used by this script ***before*** using it. + * * You are choosing to use this setup, and if you point the finger at me for * messing up your instance, I will laugh at you. */ @@ -29,14 +29,6 @@ This repository dockerizes it for easier deployment.
-## Features - -- 100% generic -- Everything is customizable -- Zero special host dependencies -- Configuration is not compile-time -- "It just works" - ## Alternatives If this setup is a bit overwhelming there are a lot of other great dockerfiles @@ -46,104 +38,110 @@ or guides from the community. A few are linked below. This list is not exhaustiv - [RX14/iscute.moe](https://github.com/RX14/kurisu.rx14.co.uk/blob/master/services/iscute.moe/pleroma/Dockerfile) - [rysiek/docker-pleroma](https://git.pleroma.social/rysiek/docker-pleroma) -## Installing Pleroma +## Docs + +### Prerequisites + +- 500mb of free HDD space +- `m4` and `awk` in remotely recent versions +- `curl` or `wget` if you want smarter build caches and commands like `./pleroma mod` +- `jq` and `dialog` if you want to use `./pleroma mod` +- Bash 4.0+ (fancy scripting stuff) +- Docker 18.06.0+ and docker-compose 1.22.0-rc1+ (We need compose file format 3.7+ for `init:`) + +### Installation - Clone this repository -- Copy `.env.dist` to `.env` -- Edit `.env` (see "Configuring Pleroma" section below) -- Run `./pleroma build` and `./pleroma start` +- Create a `config.exs` and `.env` file +- Run `./pleroma build` and `./pleroma up` - Profit! -## Updating Pleroma +### Updates -Just run `./pleroma build` again and `./pleroma start` afterwards. +Run `./pleroma build` again and start the updated image with `./pleroma up`. -You don't need to shutdown pleroma while compiling the new release. +You don't need to stop your pleroma server for either of those commands. -Every time you run `./pleroma build` the script will fetch all upstream changes and checkout `PLEROMA_VERSION`. -This means that setting `PLEROMA_VERSION` to a branch enables rolling-release updates while setting -it to a tag or commit-hash pins the version. +### Maintenance -## Maintaining Pleroma +Pleroma maintenance is usually done with mix tasks. +You can run these tasks in your running pleroma server using `./pleroma mix [task] [arguments...]`. +If you need to fix some bigger issues you can also spawn a shell with `./pleroma enter`. -Pleroma maintenance is usually done with premade mix tasks.
-You can run these tasks using `./pleroma mix [task] [arguments...]`.
-If you need to fix some bigger issues you can also spawn a shell using `./pleroma enter`. +### Customization -## Customizing Pleroma +Add your customizations (and their folder structure) to `custom.d/`. +They will be mounted and symlinked into the right place when the container starts. +You can even replace/patch pleroma’s code with this, because the project is recompiled at startup if needed. -Just add your customizations (and their folder structure) to `custom.d`.
-They will be mounted and symlinked into the right place when the container starts.
-You can even replace/patch pleroma's code with this, because the project is recompiled at startup.
- -In general: Prepending `custom.d/` to pleroma's customization guides should work all the time.
-Check them out in the [official pleroma wiki](https://git.pleroma.social/pleroma/pleroma/wikis/home). +In general: Prepending `custom.d/` to pleroma’s customization guides should work all the time.
+Check them out in the official pleroma wiki. For example: A custom thumbnail now goes into `custom.d/priv/static/instance/thumbnail.jpeg` instead of `priv/static/instance/thumbnail.jpeg`. -Note: Since `custom.d` needs to be accessible at runtime by the pleroma process, the container will automatically chown these files to `$UID:$GID` from your `.env` file. +### Patches -## Configuring Pleroma +Works exactly like customization, but we have a neat little helper here. -pleroma-docker tries to stay out of your way as much as possible while providing -a good experience for both you and your users. It thus supports multiple -"operation modes" and quite some config variables which you can mix and match. +Use `./pleroma mod [regex]` to mod any file that ships with pleroma, without having to type the complete path.
-This guide will explain some of the tricky `.env` file parts as detailed as possible (but you should still read the comments in there). +### Configuration -Since this setup [injects code](https://glitch.sh/sn0w/pleroma-docker/blob/master/docker-config.exs) into pleroma that moves it's configuration into the environment (ref ["The Twelve-Factor App"](https://12factor.net/)), -the built image is 100% reusable and can be shared/replicated across multiple hosts. -To do that just run `./pleroma build` as usual and then tag your image to whatever you want. -Just make sure to start the replicated container with `env_file:` or all required `-e` pairs. +All the pleroma options that you put into your `*.secret.exs` now go into `config.exs`. -#### Storing Data +`.env` stores config values that need to be known at orchestration time.
+They should be self-explaining but here's some bonus info on important ones: -Currently all data is stored in subfolders of `DOCKER_DATADIR` which will be bind-mounted into the container by docker. +#### Data Storage (`DOCKER_DATADIR`) -We'll evaluate named volumes as an option in the future but they're currently not supported. +A folder that will be bind-mounted into the container.
+This is where pleroma and postgres will store their data. #### Database (`SCRIPT_DEPLOY_POSTGRES`) Values: `true` / `false` -By default pleroma-docker deploys a postgresql container and links it to pleroma's container as a zero-config data store. If you already have a postgres database or want to host postgres on a physically different machine set this value to `false`. Make sure to set the `POSTGRES_*` variables when doing that. +By default pleroma-docker deploys a postgresql container and links it to pleroma’s container as a zero-config data store. +If you already have a postgres database or want to host it on a physically different machine, set this value to `false`. +Make sure to edit the `config :pleroma, Pleroma.Repo` variables when doing that. #### Reverse Proxy (`SCRIPT_USE_PROXY`) Values: `traefik` / `nginx` / `manual` -Pleroma is usually run behind a reverse-proxy. +Pleroma is usually run behind a reverse-proxy.
Pleroma-docker gives you multiple options here. ##### Traefik -In traefik-mode we will generate a pleroma container with traefik labels. -These will be picked up at runtime to dynamically create a reverse-proxy -configuration. This should 'just work' if `watch=true` and `exposedByDefault=false` are set in the `[docker]` section of your `traefik.conf`. SSL will also 'just work' once you add a matching `[[acme.domains]]` entry. +In traefik-mode we will generate a pleroma container with traefik-compatible labels. +These will be picked up at runtime to dynamically create a reverse-proxy configuration. +This should 'just work' if `watch=true` and `exposedByDefault=false` are set in the `[docker]` section of your `traefik.conf`. +SSL will also 'just work' once you add a matching `[[acme.domains]]` entry in there. ##### NGINX -In nginx-mode we will generate a bare nginx container that is linked to the -pleroma container. The nginx container is absolutely unmodified and expects to -be configured by you. The nginx file in [Pleroma's Repository](https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma.nginx) is a good starting point. +In nginx-mode we will generate a bare nginx container that is linked to pleroma. +The nginx container is absolutely unmodified and expects to be configured by you. +The nginx file in [Pleroma's Repository](https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma.nginx) is a good starting point. We will mount your configs like this: -``` +```txt custom.d/server.nginx -> /etc/nginx/nginx.conf custom.d/vhost.nginx -> /etc/nginx/conf.d/pleroma.conf ``` To reach your pleroma container from inside nginx use `proxy_pass http://pleroma:4000;`. -Set `SCRIPT_PORT_HTTP` and `SCRIPT_PORT_HTTPS` to the ports you want to listen on. +Set `SCRIPT_PORT_HTTP` and `SCRIPT_PORT_HTTPS` to the ports you want to listen on.
Specify the ip to bind to in `SCRIPT_BIND_IP`. These values are required. The container only listens on `SCRIPT_PORT_HTTPS` if `SCRIPT_ENABLE_SSL` is `true`. ##### Apache / httpd -Just like nginx-mode this starts an unmodified apache server that expects to be -configured by you. Again [Pleroma's Config](https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma-apache.conf) is a good starting point. +Just like nginx-mode this starts an unmodified apache server that expects to be configured by you.
+Again [Pleroma's Config](https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma-apache.conf) is a good starting point. We will mount your configs like this: ``` @@ -162,8 +160,9 @@ The container only listens on `SCRIPT_PORT_HTTPS` if `SCRIPT_ENABLE_SSL` is `tru In manual mode we do not create any reverse proxy for you. You'll have to figure something out on your own. -This mode also doesn't bind to any IP or port. -You'll have to forward something to the container's IP. +If `SCRIPT_BIND_IN_MANUAL` is `true` we will forward `pleroma:4000` to `${SCRIPT_BIND_IP}:${SCRIPT_PORT_HTTP}`. + +**Pleroma's internal SSL implementation is currently not supported.** #### SSL (`SCRIPT_ENABLE_SSL`) diff --git a/config.dist.exs b/config.dist.exs new file mode 100644 index 0000000..d5b477e --- /dev/null +++ b/config.dist.exs @@ -0,0 +1,86 @@ +use Mix.Config + +# pleroma/pleroma/pleroma are the default credentials for the +# managed database container. "db" is the default interlinked hostname. +# You shouldn't need to change this unless you modifed .env +config :pleroma, Pleroma.Repo, + adapter: Ecto.Adapters.Postgres, + username: "pleroma", + password: "pleroma", + database: "pleroma", + hostname: "db", + pool_size: 10 + +# vvv Your awesome config options go here vvv + +### +# Here are some example values. +# Uncomment what you need or delete it all. +# +# Want to use the config generator instead? +# Try `./pleroma mix pleroma.instance gen` and then `./pleroma cp /home/pleroma/pleroma/config/generated_config.exs config.exs`. +# +# Need some inspiration? +# Take a look at https://git.pleroma.social/pleroma/pleroma/tree/develop/config +### + +# config :pleroma, Pleroma.Web.Endpoint, +# url: [host: "example.com", scheme: "https", port: 443], +# secret_key_base: "" + +# config :pleroma, :instance, +# name: "example instance", +# email: "example@example.com", +# limit: 5000, +# registrations_open: true, +# dedupe_media: false + +# config :pleroma, :media_proxy, +# enabled: false, +# redirect_on_failure: true +# base_url: "https://cache.example.com" + +# Configure web push notifications +# config :web_push_encryption, :vapid_details, +# subject: "mailto:example@example.com", +# public_key: "", +# private_key: "" + +# Enable Strict-Transport-Security once SSL is working: +# config :pleroma, :http_security, +# sts: true + +# Configure S3 support if desired. +# The public S3 endpoint is different depending on region and provider, +# consult your S3 provider's documentation for details on what to use. +# +# config :pleroma, Pleroma.Uploaders.S3, +# bucket: "some-bucket", +# public_endpoint: "https://s3.amazonaws.com" +# +# Configure S3 credentials: +# config :ex_aws, :s3, +# access_key_id: "xxxxxxxxxxxxx", +# secret_access_key: "yyyyyyyyyyyy", +# region: "us-east-1", +# scheme: "https://" +# +# For using third-party S3 clones like wasabi, also do: +# config :ex_aws, :s3, +# host: "s3.wasabisys.com" + +# Configure Openstack Swift support if desired. +# +# Many openstack deployments are different, so config is left very open with +# no assumptions made on which provider you're using. This should allow very +# wide support without needing separate handlers for OVH, Rackspace, etc. +# +# config :pleroma, Pleroma.Uploaders.Swift, +# container: "some-container", +# username: "api-username-yyyy", +# password: "api-key-xxxx", +# tenant_id: "", +# auth_url: "https://keystone-endpoint.provider.com", +# storage_url: "https://swift-endpoint.prodider.com/v1/AUTH_/", +# object_url: "https://cdn-endpoint.provider.com/" +# diff --git a/docker-compose.m4 b/docker-compose.m4 index 1a1b155..aacbc0f 100644 --- a/docker-compose.m4 +++ b/docker-compose.m4 @@ -7,7 +7,7 @@ define(, <${upcase($1):?upcase($1)}>) define(, <${upcase($1):-$2}>) { - "version": "3", + "version": "3.7", ifdef(<__DOCKER_NETWORK>, < "networks": { @@ -88,39 +88,20 @@ define(, <${upcase($1):-$2}>) "env()", "env()", "env()", - "env_fb(, )", + "env_fb(, )" ] }, + "init": true, "restart": "unless-stopped", "links": [ ifelse(__SCRIPT_DEPLOY_POSTGRES, true, <"db">) ], "environment": [ - "env_fb(, )", - - "env_fb(, )", - "env()", - "env()", - "env()", - - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env()", - "env_fb(, )" + "env_fb(, )" ], "volumes": [ - "./custom.d:/custom.d", + "./custom.d:/custom.d:ro", + "./config.exs:/home/pleroma/pleroma/config/prod.secret.exs:ro", "env_inline()/uploads:env_inline_fb(, )" ], "labels": [ diff --git a/docker-config.exs b/docker-config.exs deleted file mode 100644 index 5207e38..0000000 --- a/docker-config.exs +++ /dev/null @@ -1,71 +0,0 @@ -use Mix.Config - -defmodule Docker do - def env(shortname, verbatim \\ false) do - # Get var - name = ((if verbatim, do: "", else: "pleroma_") <> Atom.to_string(shortname)) |> String.upcase() - raw_var = System.get_env(name) - - if raw_var == nil do - raise "Could not find #{name} in environment. Please define it and try again." - end - - # Match type and cast if needed - if String.contains?(raw_var, ":") do - var_parts = String.split(raw_var, ":", parts: 2) - - type = Enum.at(var_parts, 0) - var = Enum.at(var_parts, 1) - - func = case type do - "int" -> fn(x) -> Integer.parse(x) |> elem(0) end - "bool" -> fn(x) -> x == "true" end - "string" -> fn(x) -> x end - _ -> if verbatim do - fn(x) -> x end - else - raise "Unknown type #{type} used in variable #{raw_var}." - end - end - - func.(var) - else - raw_var - end - end -end - -config :logger, level: String.to_atom(Docker.env(:loglevel) || "info") - -config :pleroma, Pleroma.Web.Endpoint, - url: [ - host: Docker.env(:url), - scheme: Docker.env(:scheme), - port: Docker.env(:port) - ], - secret_key_base: Docker.env(:secret_key_base) - -config :pleroma, Pleroma.Upload, - uploads: Docker.env(:uploads_path) - -config :pleroma, :chat, - enabled: Docker.env(:chat_enabled) - -config :pleroma, :instance, - name: Docker.env(:name), - email: Docker.env(:admin_email), - limit: Docker.env(:max_notice_chars), - registrations_open: Docker.env(:registrations_open) - -config :pleroma, :media_proxy, - enabled: Docker.env(:media_proxy_enabled), - redirect_on_failure: Docker.env(:media_proxy_redirect_on_failure), - base_url: Docker.env(:media_proxy_url) - -config :pleroma, Pleroma.Repo, - adapter: Ecto.Adapters.Postgres, - username: Docker.env(:postgres_user, true), - password: Docker.env(:postgres_password, true), - database: Docker.env(:postgres_db, true), - hostname: Docker.env(:postgres_ip, true), - pool_size: Docker.env(:db_pool_size) diff --git a/entrypoint.sh b/entrypoint.sh index 35f5365..789dcaf 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,9 +1,33 @@ -#!/bin/bash +#!/bin/ash +# shellcheck shell=dash set -e -set -x -mix deps.get -mix ecto.create +if [ -n "$BUILDTIME" ]; then + echo "#> Preparing compilation..." + + mix local.rebar --force + mix local.hex --force + + echo "#> Compiling..." + mix deps.get + mix compile + exit 0 +fi + +echo "#> Applying customizations and patches.." +rsync -av /custom.d/ /home/pleroma/pleroma/ + +echo "#> Recompiling..." +mix compile + +echo "#> Waiting until database is ready..." +while ! pg_isready -U pleroma -d postgres://db:5432/pleroma -t 1; do + sleep 1s +done + +echo "#> Upgrading database..." mix ecto.migrate + +echo "#> Liftoff!" exec mix phx.server diff --git a/pleroma b/pleroma index cc00756..8631c47 100755 --- a/pleroma +++ b/pleroma @@ -1,72 +1,72 @@ #!/bin/bash +######################################################### +# Options # +######################################################### + set -e set -o pipefail -print_help() { - echo " -Pleroma Maintenance Script +######################################################### +# Globals # +######################################################### -Usage: - $0 [action] - -Actions: - build Rebuild the pleroma container. - - dump Dump the generated docker-compose.yml to stdout. - - debug [bin] [args...] Launches a new pleroma container but uses \$bin instead of phx.server as entrypoint. - **Warning**: This is intended for debugging pleroma with tools like :debugger and :observer. - It thus forwards your X-Server into docker and temporarily fiddles with your xhost - access controls. If this is a security concern for you, please export NO_X_FORWARDING=1 - before launching a debugger session. - - enter Spawn a shell inside the container for debugging/maintenance. - This command does not link to the postgres container. - If you need that use #debug instead. - - logs Show the current container logs. - - mix [task] [args...] Run a mix task without entering the container. - - mod [file] Creates the file in custom.d and downloads the content from pleroma.social. - The download respects your \$PLEROMA_VERSION from .env. - - passthrough / p [...] Pass any custom command to docker-compose. - - restart Executes #stop and #start respectively. - - start / up Start pleroma and sibling services. - - stop / down Stop pleroma and sibling services. - - status / ps Show the current container status. - -Environment: - DEBUG can be used to modify the loglevel. - DEBUG=1 prints all commands before they are executed. - DEBUG=2 prints all bash statements before they are executed (a lot). - - SHOPT can be used to modify shell options. - Pass a list of options to this variable like SHOPT='-x -e'. - -e is always on unless you set it to +e. - - For setting long options with -o use a colon (:) instead of a space - to seperate the option from -o. For example: SHOPT='-x -e -o:pipefail'. - -Contributing: - You can report bugs or contribute to this project at: - https://glitch.sh/sn0w/pleroma-docker -" -} +readonly GITLAB_URI="https://git.pleroma.social" +readonly PREFIX_API="api/v4/projects/pleroma%2Fpleroma/repository" +readonly ENDPOINT_REPO="pleroma/pleroma.git" +readonly ENDPOINT_FILE="pleroma/pleroma/raw" +readonly ENDPOINT_LIST="pleroma/pleroma/files" +readonly ENDPOINT_TAG="$PREFIX_API/tags" +readonly ENDPOINT_BLOB="$PREFIX_API/blobs" +readonly ENDPOINT_BRANCH="$PREFIX_API/branches" flags="" +######################################################### +# Helpers # +######################################################### + +has_command() { + if command -v 1>/dev/null 2>&1 "$1"; then + return 0 + else + return 1 + fi +} + +require_command() { + if ! has_command "$1"; then + printf "\nError: This action requires the command '%s' in your PATH.\n" "$1" + exit 1 + fi +} + +require_file() { + if [[ ! -f $1 ]]; then + echo "File missing: '$1' (Example at: '$2')" + FILE_FAILED=1 + fi +} + +throw_file_errors() { + if [[ -n "$FILE_FAILED" ]]; then + echo "" + echo "Please create the missing files first." + echo "The script will now exit." + exit 1 + fi +} + render_template() { + require_command m4 + require_command awk + m4 $flags docker-compose.m4 | awk 'NF' } docker_compose() { + require_command docker-compose + docker-compose \ -f <(render_template) \ --project-directory . \ @@ -74,12 +74,6 @@ docker_compose() { } load_env() { - if [[ ! -f .env ]]; then - echo "Please create a .env file first" - echo "(Copy .env.dist to .env for a template)" - exit 1 - fi - while read -r line; do if [[ "$line" == \#* ]] || [[ -z "$line" ]]; then continue; @@ -90,32 +84,131 @@ load_env() { done < .env } -action__build() { docker_compose build --build-arg __BUST_CACHE="$(date +%s)" server; } -action__dump() { cat <(render_template); } -action__enter() { docker_compose exec server ash -c 'cd /pleroma && ash'; } -action__logs() { docker_compose logs -f; } -action__mix() { docker_compose exec server ash -c "cd /pleroma && mix $*"; } -action__passthrough() { docker_compose $*; } -action__p() { action__passthrough $*; } +download_file() { # $1: source, $2: target + if has_command curl; then + curl -sSL "$1" -o "$2" + elif has_command wget; then + wget "$1" -O "$2" + else + printf "\nError: This action requires either curl or wget in your PATH.\n" + exit 1 + fi +} -action__restart() { action__stop; action__start; } +request_file_content() { # $1: source + if has_command curl; then + curl -sSL "$1" + elif has_command wget; then + wget "$1" -O- 2>/dev/null + else + printf "\nError: This action requires either curl or wget in your PATH.\n" + exit 1 + fi +} -action__start() { docker_compose up --remove-orphans -d; } -action__up() { action__start; } +######################################################### +# Subcommands # +######################################################### -action__stop() { docker_compose down; } -action__down() { action__stop; } +action__build() { + local cacheTag="" -action__status() { docker_compose ps; } -action__ps() { action__status; } + # Alternative 1: Get tags or branches from git (if installed) + if [[ -z "$cacheTag" ]] && has_command git; then + set +o pipefail + local resolvedHash + resolvedHash="$(git ls-remote $GITLAB_URI/$ENDPOINT_REPO | grep "/$PLEROMA_VERSION" | awk '{ print $1 }')" + set -o pipefail + + if [[ -n "$resolvedHash" ]]; then + cacheTag="$resolvedHash" + fi + fi + + # Alternative 2: Current time with date or awk + if [[ -z "$cacheTag" ]] && has_command date; then + cacheTag="$(date '+%s')" + fi + + if [[ -z "$cacheTag" ]] && has_command awk; then + cacheTag="$(awk 'BEGIN { srand(); print srand() }')" + fi + + # Last resort: Constant value, user will need to run `docker system prune` + if [[ -z "$cacheTag" ]]; then + echo "" + echo "Warning: Cannot set a reliably unique cache tag." + echo " You may be running outdated code!" + echo "" + + cacheTag="broken-host-env" + fi + + docker_compose build --build-arg __CACHE_TAG="$cacheTag" server +} + +action__dump() { + cat <(render_template) +} + +action__enter() { + docker_compose exec server sh -c 'cd ~/pleroma && bash' +} + +action__logs() { + docker_compose logs "$@" +} + +action__mix() { + docker_compose exec server sh -c "cd ~/pleroma && mix $*" +} + +action__passthrough() { + docker_compose "$@" +} + +action__p() { + action__passthrough "$@" +} + +action__restart() { + action__stop + action__start +} + +action__start() { + docker_compose up --remove-orphans -d +} + +action__up() { + action__start +} + +action__stop() { + docker_compose down +} + +action__down() { + action__stop +} + +action__status() { + docker_compose ps +} + +action__ps() { + action__status +} -### -# This function rips out the mix caches from the container -# in order to speed up rebuilds during debugging/modding sessions. -# To persist the changes, the user still needs to rebuild the container. -### action__debug() { - debug_mounts="-v $(pwd)/custom.d:/custom.d -v $(pwd)/debug.d/build:/home/pleroma/pleroma/_build -v $(pwd)/debug.d/deps:/home/pleroma/pleroma/deps" + require_command xhost + + local debug_mounts + debug_mounts=" + -v $(pwd)/custom.d:/custom.d \ + -v $(pwd)/debug.d/build:/home/pleroma/pleroma/_build \ + -v $(pwd)/debug.d/deps:/home/pleroma/pleroma/deps \ + " if [[ ! -d ./debug.d ]]; then mkdir -p ./debug.d/{build,deps} @@ -127,24 +220,130 @@ action__debug() { action__stop - 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' + 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' - x_flags="" + local x_flags="" if [[ $NO_X_FORWARDING != 1 ]]; then x_flags="-e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix" fi [[ $NO_X_FORWARDING == 1 ]] || xhost +local:root - docker_compose run --rm -u pleroma -w /home/pleroma/pleroma $debug_mounts $x_flags server bash -c "cp -rvf /custom.d/* /home/pleroma/pleroma && $*" + docker_compose run --rm -u pleroma -w /home/pleroma/pleroma "$debug_mounts" "$x_flags" server bash -c "cp -rvf /custom.d/* /home/pleroma/pleroma && $*" [[ $NO_X_FORWARDING == 1 ]] || xhost -local:root } action__mod() { - echo "Preparing 'custom.d/$1' for modding..." - install -D <(echo '') ./custom.d/$1 - wget -O ./custom.d/$1 https://git.pleroma.social/pleroma/pleroma/raw/$PLEROMA_VERSION/$1 + require_command dialog + require_command jq + require_command curl + + if [[ ! -d ./debug.d ]]; then + mkdir ./debug.d + fi + + if [[ ! -f ./debug.d/mod_files.json ]] || [[ -n "$(find ./debug.d/mod_files.json -mmin +5)" ]]; then + curl -sSL -# "$GITLAB_URI/$ENDPOINT_LIST/$PLEROMA_VERSION?format=json" > ./debug.d/mod_files.json + + if [[ -f ./debug.d/mod_files.lst ]]; then + rm ./debug.d/mod_files.lst + fi + + jq -r 'map("\(.)\n") | add' <./debug.d/mod_files.json >./debug.d/mod_files.lst + fi + + if [[ -f ./debug.d/mod_files.lst ]] && [[ -r ./debug.d/mod_files.lst ]]; then + choices="" + + while read -r candidate; do + choices="$choices $candidate $(echo "$candidate" | rev | cut -d/ -f1 | rev)" + done <<< "$(grep -E ".*$1.*" <./debug.d/mod_files.lst)" + + res=$(mktemp) + dialog --menu "Select the file you want to modify:" 35 80 30 $choices 2>"$res" + choice=$(cat "$res") + + install -D <(echo '') "./custom.d/$choice" + curl -sSL -# "$GITLAB_URI/$ENDPOINT_FILE/$PLEROMA_VERSION/$choice" > "./custom.d/$choice" + else + install -D <(echo '') "./custom.d/$1" + curl -sSL -# "$GITLAB_URI/$ENDPOINT_FILE/$PLEROMA_VERSION/$1" > "./custom.d/$1" + fi } +action__cp() { + container="$(docker_compose ps -q server)" + + echo "$container:$1 -> $2" + docker cp "$container:$1" "$2" +} + +######################################################### +# Help # +######################################################### + +print_help() { + echo " +Pleroma Maintenance Script + +Usage: + $0 [action] [action-args...] + +Actions: + build (Re)build the pleroma container. + + dump Dump the generated docker-compose.yml to stdout. + + debug [bin] [args...] Launches a new pleroma container but uses \$bin instead of phx.server as entrypoint. + **Warning**: This is intended for debugging pleroma with tools like :debugger and :observer. + It thus forwards your X-Server into docker and temporarily fiddles with your xhost + access controls. If this is a security concern for you, please export NO_X_FORWARDING=1 + before launching a debugger session. + + enter Spawn a shell inside the container for debugging/maintenance. + This command does not link to the postgres container. + If you need that use #debug instead. + + logs Show the current container logs. + + mix [task] [args...] Run a mix task without entering the container. + + mod [file] Creates the file in custom.d and downloads the content from pleroma.social. + The download respects your \$PLEROMA_VERSION from .env. + + passthrough / p [...] Pass any custom command to docker-compose. + + restart Executes #stop and #start respectively. + + start / up Start pleroma and sibling services. + + stop / down Stop pleroma and sibling services. + + status / ps Show the current container status. + + copy / cp [source] [target] Copy a file from your pc to the pleroma container. + This operation only works in one direction. + For making permanent changes to the container use custom.d. + +Environment: + DEBUG can be used to modify the loglevel. + DEBUG=1 prints all commands before they are executed. + DEBUG=2 prints all bash statements before they are executed (a lot). + + SHOPT can be used to modify shell options. + Pass a list of options to this variable like SHOPT='-x -e'. + For setting long options with -o use a colon (:) instead of a space + to seperate the option from -o. For example: SHOPT='-x -e -o:pipefail'. + +Contributing: + You can report bugs or contribute to this project at: + https://glitch.sh/sn0w/pleroma-docker +" +} + +######################################################### +# Main # +######################################################### + # Check if there is any command at all if [[ -z "$1" ]]; then print_help @@ -152,18 +351,18 @@ if [[ -z "$1" ]]; then fi # Check for SHOPTs -if [[ ! -z "$SHOPT" ]]; then +if [[ -n "$SHOPT" ]]; then for opt in $SHOPT; do if [[ $opt =~ ":" ]]; then - set -o ${opt//-o:/} + set -o "${opt//-o:/}" else - set $opt + set "$opt" fi done fi # Check for DEBUG -if [[ ! -z "$DEBUG" ]]; then +if [[ -n "$DEBUG" ]]; then if [[ $DEBUG == 1 ]]; then export DEBUG_COMMANDS=1 elif [[ $DEBUG == 2 ]]; then @@ -171,19 +370,36 @@ if [[ ! -z "$DEBUG" ]]; then fi fi +# Check if the option is "help" +case "$1" in + "help"|"h"|"--help"|"-h"|"-?") + print_help + exit 0 + ;; +esac + +# Check if the called command exists +func="action__${1}" +if ! type -t "$func" 1>/dev/null 2>&1; then + echo "Unknown flag or subcommand." + echo "Try '$0 help'" + exit 1 +fi + +# Fail if mandatory files are missing +require_file ".env" ".env.dist" +require_file "config.exs" "config.dist.exs" +throw_file_errors + # Parse .env load_env -# Guess function name of current command -# and then check for it's existance. -func="action__${1}" +# Handle DEBUG=2 +[[ $DEBUG != 1 ]] || set -x -if type -t $func 2>&1 1>/dev/null; then - shift - [[ $DEBUG != 1 ]] || set -x - $func $@ - { [[ $DEBUG != 1 ]] || set +x; } 2>/dev/null -else - print_help - exit 1 -fi +# Jump to called function +shift +$func "$@" + +# Disable debug mode +{ [[ $DEBUG != 1 ]] || set +x; } 2>/dev/null