diff --git a/Dockerfile b/Dockerfile index 9c4c6d3..9cfc38d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM elixir:1.11.4-alpine +FROM elixir:1.15.4-alpine ARG PLEROMA_VER=develop ARG UID=911 @@ -26,6 +26,12 @@ WORKDIR /pleroma RUN git clone -b develop https://git.pleroma.social/pleroma/pleroma.git /pleroma \ && git checkout ${PLEROMA_VER} +#WORKDIR /pleroma/lib/pleroma/web/activity_pub/mrf +#RUN wget \ +# put your links for MRFs in here +#WORKDIR /pleroma + + RUN echo "import Mix.Config" > config/prod.secret.exs \ && mix local.hex --force \ && mix local.rebar --force \ diff --git a/LICENSE b/LICENSE index 19a30af..e1f59b6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2018 Angristan +Copyright (c) 2023 Bronze Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 591b252..2f2b02e 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,9 @@ It actually consists of two components: a backend, named simply Pleroma, and a u Its main advantages are its lightness and speed. -![Pleroma](https://i.imgur.com/VftiTlR.png) +## Why Docker? -_Pleromians trying to understand the memes_ - -## Features - -- Based on the elixir:alpine image -- Ran as an unprivileged user -- It works great - -Sadly, this is not a reusable (e.g. I can't upload it to the Docker Hub), because for now Pleroma needs to compile the configuration. 😢 -Thus you will need to build the image yourself, but I explain how to do it below. +Boxing up Pleroma in a docker container allows it to be portable, and keeps your host system clean. The software and its dependencies will all be under the `pleroma_web` container (created with the lightweight elixir:alpine base image) while its postgres database will live under `pleroma_db` image. Only port 4000 will be exposed under localhost. ## Build-time variables @@ -29,140 +20,63 @@ Thus you will need to build the image yourself, but I explain how to do it below ### Installation -Create a folder for your Pleroma instance. Inside, you should have `Dockerfile` and `docker-compose.yml` from this repo. +This container is meant to run behind a reverse proxy. Please set up letsencrypt and a Nginx reverse proxy in a container or on your host by using the [example Nginx config](https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma.nginx). There's also a config file in the `extras` folder you could take a look at. -Here is the `docker-compose.yml`. You should change the `POSTGRES_PASSWORD` variable. +Log into your server and clone this repository with: -```yaml -version: "3.8" +`git clone https://kitsunemimi.club/git/bronze/docker-pleroma` -services: - db: - image: postgres:12.1-alpine - container_name: pleroma_db - restart: always - environment: - POSTGRES_USER: pleroma - POSTGRES_PASSWORD: ChangeMe! - POSTGRES_DB: pleroma - volumes: - - ./postgres:/var/lib/postgresql/data +Go into the new docker-pleroma folder and run: - web: - image: pleroma - container_name: pleroma_web - restart: always - ports: - - "4000:4000" - build: - context: . - # Feel free to remove or override this section - # See 'Build-time variables' in README.md - args: - - "UID=911" - - "GID=911" - - "PLEROMA_VER=develop" - volumes: - - ./uploads:/var/lib/pleroma/uploads - - ./static:/var/lib/pleroma/static - - ./config.exs:/etc/pleroma/config.exs:ro - # optional, see 'Config Override' section in README.md - # - ./config-override.exs:/var/lib/pleroma/config.exs:ro - environment: - DOMAIN: example.com - INSTANCE_NAME: Pleroma - ADMIN_EMAIL: admin@example.com - NOTIFY_EMAIL: notify@example.com - DB_USER: pleroma - DB_PASS: ChangeMe! - DB_NAME: pleroma - depends_on: - - db -``` +`sh ./scripts/setup.sh` -Create the upload and config folder and give write permissions for the uploads: +This first time setup script will ask you a few questions, generate a random password for your postgres database, put the results into your docker compose and create an admin account. -```sh -mkdir uploads config -chown -R 911:911 uploads -``` +Remember that password reset link at the end will only work if your reverse proxy is configured and running (duh!). -Pleroma needs the `citext` PostgreSQL extension, here is how to add it: +Any further configuration can be done as soon as you log into your admin account, over admin-fe. It will be the speedometer icon right next to the cog on the top right of the webpage. -```sh -docker-compose up -d db -docker exec -i pleroma_db psql -U pleroma -c "CREATE EXTENSION IF NOT EXISTS citext;" -docker-compose down -``` +### Maintenance -Optionally configure Pleroma, see [Config Override](#config-override). -You can now build the image. 2 way of doing it: +A very helpful [bash alias](https://www.digitalocean.com/community/tutorials/an-introduction-to-useful-bash-aliases-and-functions) for managing your pleroma instance: -```sh -docker-compose build -# or -docker build -t pleroma . -``` +`alias pleroma-ctl='docker exec -it pleroma_web sh ./bin/pleroma_ctl'` -I prefer the latter because it's more verbose but this will ignore any build-time variables you have set in `docker-compose.yml`. +Now you can easily run any of the CLI commands cited in the [documentation](https://docs-develop.pleroma.social/backend/administration/CLI_tasks/user/). -You can now launch your instance: +#### Common tasks -```sh -docker-compose up -d -``` +Update to the latest pleroma-fe frontend using: -The initial creation of the database schema will be done automatically. Check if everything went well with: +`sh ./scripts/update-plfe.sh` -```sh -docker logs -f pleroma_web -``` +Update/rebuild the pleroma backend using: -Make a new admin user using docker exec (replace fakeadmin with any username you'd like): +`sh ./scripts/rebuild.sh` -```sh -docker exec -it pleroma_web sh ./bin/pleroma_ctl user new fakeadmin admin@test.net --admin -``` +Vacuum your database with this script: -You can now setup a Nginx reverse proxy in a container or on your host by using the [example Nginx config](https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma.nginx). +`sh ./scripts/vacuum.sh` -### Update +Emojis are under `./static/emoji` so drag and drop your folders there. -By default, the Dockerfile will be built from the latest commit of the `develop` branch as Pleroma does not have releases for now. +#### Backups -Thus to update, just rebuild your image and recreate your containers: +Backups can be done by copying the whole docker-pleroma folder. How you make this copy I'll leave up to you. -```sh -docker-compose pull # update the PostgreSQL if needed -docker-compose build . -# or -docker build -t pleroma . -docker-compose run --rm web mix ecto.migrate # migrate the database if needed -docker-compose up -d # recreate the containers if needed -``` +For my own instance, I take a btrfs snapshot of this folder and make a tarball / squashfs archive of that snapshot. Should SHTF I have the snapshots and tarballs to fall back on! -If you want to run a specific commit, you can use the `PLEROMA_VER` variable: +However you choose to do it, make sure to `docker compose down` before making the backup, you dont want anything modified as you're making the copy. -```sh -docker build -t pleroma . --build-arg PLEROMA_VER=develop # a branch -docker build -t pleroma . --build-arg PLEROMA_VER=a9203ab3 # a commit -docker build -t pleroma . --build-arg PLEROMA_VER=v2.0.7 # a version -``` +#### Upgrading database version -`a9203ab3` being the hash of the commit. (They're [here](https://git.pleroma.social/pleroma/pleroma/commits/develop)) - -This value can also be set through `docker-compose.yml` as seen in the example file provided in this repository. - -## Config Override - -By default the provided `docker-compose.yml` file mounts `config.exs` in the Pleroma container, this file is a dynamic configuration that sources some values from the environment variables provided to the container (variables like `ADMIN_EMAIL` etc.). - -For those that want to change configuration that is not exposed through environment variables there is the option to mount the `config-override.exs` file which can than be modified to your satisfaction. Values set in this file will override anything set in `config.exs`. The override file provided in this repository disables new registrations on your instance, as an example. +Please see `UPDATE-DB.md` ## Other Docker images -Here are other Pleroma Docker images that helped me build mine: - +- [angristan/docker-pleroma](https://github.com/angristan/docker-pleroma) (the one this is based off of!) +- [verita84/pleroma](https://git.poster.place/verita84/pleroma) +- [verita84/akkoma](https://git.poster.place/verita84/akkoma) - [potproject/docker-pleroma](https://github.com/potproject/docker-pleroma) - [rysiek/docker-pleroma](https://git.pleroma.social/rysiek/docker-pleroma) - [RX14/iscute.moe](https://github.com/RX14/kurisu.rx14.co.uk/blob/master/services/iscute.moe/pleroma/Dockerfile) diff --git a/UPDATE-DB.md b/UPDATE-DB.md new file mode 100644 index 0000000..921d277 --- /dev/null +++ b/UPDATE-DB.md @@ -0,0 +1,29 @@ +# HOW TO UPDATE POSTGRES DATABASE + +If you want to upgrade your database version (say from postgres 14 to 15) + +1. Create a backup of your instance! Or at least a copy of the postgres folder! + +2. Dump your database with the following command: + +`docker exec -u pleroma pleroma_db pg_dump -Fc pleroma > db.dump` + +3. Change the [image tag](https://hub.docker.com/_/postgres/) for your db under `docker-compose.yml` + +4. Delete your existing postgres folder with `rm -rvf postgres` + +5. Bring up only the database container with + +`docker compose up db -d` + +6. Restore your database backup into the new database with + +`docker exec -i -u pleroma pleroma_db pg_restore -C -d postgres < db.dump` + +7. Launch pleroma_web with the following command and watch for errors + +`docker compose up web -d` + +`docker compose logs web db -f` + +Should there be any errors... well that's what backups are for! Restore from the backup you made. diff --git a/config.exs b/config.exs index 93b0313..7f9576a 100644 --- a/config.exs +++ b/config.exs @@ -4,20 +4,6 @@ config :pleroma, Pleroma.Web.Endpoint, url: [host: System.get_env("DOMAIN", "localhost"), scheme: "https", port: 443], http: [ip: {0, 0, 0, 0}, port: 4000] -config :pleroma, :instance, - name: System.get_env("INSTANCE_NAME", "Pleroma"), - email: System.get_env("ADMIN_EMAIL"), - notify_email: System.get_env("NOTIFY_EMAIL"), - limit: 5000, - registrations_open: true, - federating: true, - healthcheck: true - -config :pleroma, :media_proxy, - enabled: false, - redirect_on_failure: true, - base_url: "https://cache.domain.tld" - config :pleroma, Pleroma.Repo, adapter: Ecto.Adapters.Postgres, username: System.get_env("DB_USER", "pleroma"), @@ -26,49 +12,4 @@ config :pleroma, Pleroma.Repo, hostname: System.get_env("DB_HOST", "db"), pool_size: 10 -# Configure web push notifications -config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}" - -config :pleroma, :database, rum_enabled: false -config :pleroma, :instance, static_dir: "/var/lib/pleroma/static" -config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" - -# We can't store the secrets in this file, since this is baked into the docker image -if not File.exists?("/var/lib/pleroma/secret.exs") do - secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64) - signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8) - {web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1) - - secret_file = - EEx.eval_string( - """ - import Config - - config :pleroma, Pleroma.Web.Endpoint, - secret_key_base: "<%= secret %>", - signing_salt: "<%= signing_salt %>" - - config :web_push_encryption, :vapid_details, - public_key: "<%= web_push_public_key %>", - private_key: "<%= web_push_private_key %>" - """, - secret: secret, - signing_salt: signing_salt, - web_push_public_key: Base.url_encode64(web_push_public_key, padding: false), - web_push_private_key: Base.url_encode64(web_push_private_key, padding: false) - ) - - File.write("/var/lib/pleroma/secret.exs", secret_file) -end - -import_config("/var/lib/pleroma/secret.exs") - -# For additional user config -if File.exists?("/var/lib/pleroma/config.exs"), - do: import_config("/var/lib/pleroma/config.exs"), - else: - File.write("/var/lib/pleroma/config.exs", """ - import Config - - # For additional configuration outside of environmental variables - """) \ No newline at end of file +config :pleroma, configurable_from_database: true \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6986571..176c6fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,14 +2,14 @@ version: '3.8' services: db: - image: postgres:12.1-alpine + image: postgres:15-alpine container_name: pleroma_db restart: always healthcheck: test: ["CMD", "pg_isready", "-U", "pleroma"] environment: POSTGRES_USER: pleroma - POSTGRES_PASSWORD: ChangeMe! + POSTGRES_PASSWORD: CHANGETHEDATABASEPASSWORD! POSTGRES_DB: pleroma volumes: - ./postgres:/var/lib/postgresql/data @@ -33,7 +33,7 @@ services: args: - "UID=1000" - "GID=1000" - - "PLEROMA_VER=v2.4.2" +# - "PLEROMA_VER=v2.4.2" volumes: - ./uploads:/var/lib/pleroma/uploads - ./static:/var/lib/pleroma/static @@ -44,7 +44,7 @@ services: ADMIN_EMAIL: admin@example.com NOTIFY_EMAIL: notify@example.com DB_USER: pleroma - DB_PASS: ChangeMe! + DB_PASS: CHANGETHEDATABASEPASSWORD! DB_NAME: pleroma depends_on: - db diff --git a/extras/nginx.conf b/extras/nginx.conf new file mode 100644 index 0000000..03ff1de --- /dev/null +++ b/extras/nginx.conf @@ -0,0 +1,97 @@ +# Section of the default nginx config provided by this link +# https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma.nginx +# This is meant to be edited by you and then put under /etc/nginx/conf.d/ as a separate file! +# Dont forget to add "include /etc/nginx/conf.d/*.conf;" without the quotes to your /etc/nginx/nginx.conf file right under where index is. + +server { + server_name example.tld; + + listen 80; + listen [::]:80; + + # Uncomment this if you need to use the 'webroot' method with certbot. Make sure + # that the directory exists and that it is accessible by the webserver. If you followed + # the guide, you already ran 'mkdir -p /var/lib/letsencrypt' to create the folder. + # You may need to load this file with the ssl server block commented out, run certbot + # to get the certificate, and then uncomment it. + # + # location ~ /\.well-known/acme-challenge { + # root /var/lib/letsencrypt/; + # } + location / { + return 301 https://$server_name$request_uri; + } +} + +# Enable SSL session caching for improved performance +ssl_session_cache shared:ssl_session_cache:10m; + +server { + server_name example.tld; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + ssl_session_timeout 1d; + ssl_session_cache shared:MozSSL:10m; # about 40000 sessions + ssl_session_tickets off; + + ssl_trusted_certificate /etc/letsencrypt/live/example.tld/chain.pem; + ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_prefer_server_ciphers off; + # In case of an old server with an OpenSSL version of 1.0.2 or below, + # leave only prime256v1 or comment out the following line. + ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; + ssl_stapling on; + ssl_stapling_verify on; + + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml; + + # the nginx default is 1m, not enough for large media uploads + client_max_body_size 16m; + ignore_invalid_headers off; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + location / { + proxy_pass http://127.0.0.1:4000; + } + + # Uncomment this if you want notice compatibility routes for frontends like Soapbox. + # location ~ ^/@[^/]+/([^/]+)$ { + # proxy_pass http://127.0.0.1:4000/notice/$1; + # } + # + # location ~ ^/@[^/]+/posts/([^/]+)$ { + # proxy_pass http://127.0.0.1:4000/notice/$1; + # } + # + # location ~ ^/[^/]+/status/([^/]+)$ { + # proxy_pass http://127.0.0.1:4000/notice/$1; + # } + + location ~ ^/(media|proxy) { + proxy_cache pleroma_media_cache; + slice 1m; + proxy_cache_key $host$uri$is_args$args$slice_range; + proxy_set_header Range $slice_range; + proxy_cache_valid 200 206 301 304 1h; + proxy_cache_lock on; + proxy_ignore_client_abort on; + proxy_buffering on; + chunked_transfer_encoding on; + proxy_pass http://127.0.0.1:4000; + } +} diff --git a/scripts/db-dump.sh b/scripts/db-dump.sh new file mode 100644 index 0000000..e39b05e --- /dev/null +++ b/scripts/db-dump.sh @@ -0,0 +1,5 @@ +#!/bin/sh +docker compose down +docker compose up db -d +docker exec -u pleroma pleroma_db pg_dump -Fc pleroma > db.dump +docker compose down \ No newline at end of file diff --git a/scripts/db-restore.sh b/scripts/db-restore.sh new file mode 100644 index 0000000..5467c92 --- /dev/null +++ b/scripts/db-restore.sh @@ -0,0 +1,4 @@ +#!/bin/sh +docker compose pull db +docker compose up db -d +docker exec -i -u pleroma pleroma_db pg_restore -C -d postgres < db.dump \ No newline at end of file diff --git a/scripts/db-vacuum.sh b/scripts/db-vacuum.sh new file mode 100644 index 0000000..4c6c21c --- /dev/null +++ b/scripts/db-vacuum.sh @@ -0,0 +1,5 @@ +#!/bin/sh +docker compose down +docker compose up db -d +docker exec -it pleroma_db psql -U pleroma -d pleroma -c 'vacuum(full,analyse,verbose);' +docker compose up web -d \ No newline at end of file diff --git a/scripts/rebuild.sh b/scripts/rebuild.sh new file mode 100644 index 0000000..5b89323 --- /dev/null +++ b/scripts/rebuild.sh @@ -0,0 +1,6 @@ +#!/bin/sh +docker compose down +docker compose pull db +#docker build -t pleroma . --build-arg PLEROMA_VER=develop --no-cache +docker compose build web --no-cache +docker compose up -d \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100644 index 0000000..a8abeb8 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,28 @@ +#!/bin/sh +read -p "Enter the domain your instance will run from: " PL_DOMAIN +read -p "Enter the name of your instance: " PL_INSTANCE_NAME +read -p "Enter the admin email: " PL_ADMIN_EMAIL +read -p "Enter the notify email: " PL_NOTIFY_EMAIL + +PL_DB_PASS=`strings /dev/urandom | grep -o '[[:alnum:]]' | head -n 48 | tr -d '\n'; echo` + +sed -i -e "s/CHANGETHEDATABASEPASSWORD!/${PL_DB_PASS}/g" \ + -e "s/admin@example.com/${PL_ADMIN_EMAIL}/g" \ + -e "s/notify@example.com/${PL_NOTIFY_EMAIL}/g" \ + -e "s/Pleroma/${PL_INSTANCE_NAME}/g" \ + -e "s/example.com/${PL_DOMAIN}/g" \ +docker-compose.yml + +chmod o= config.exs + +docker compose up -d db +sleep 10 +docker exec -i pleroma_db psql -U pleroma -c "CREATE EXTENSION IF NOT EXISTS citext;" +docker compose down +docker compose build web --no-cache +docker compose up -d +sleep 10 +echo "The docker container for your instance should be up and ready, but there is no admin account..." +read -p "Enter the admin username: " PL_ADMIN_USERNAME +docker exec -it pleroma_web sh ./bin/pleroma_ctl user new "${PL_ADMIN_USERNAME}" "${PL_ADMIN_EMAIL}" --admin +echo "Please copy the reset link above and save it, and make sure to set up your reverse proxy so you can access your new instance!" \ No newline at end of file diff --git a/scripts/update-plfe.sh b/scripts/update-plfe.sh new file mode 100644 index 0000000..c838d31 --- /dev/null +++ b/scripts/update-plfe.sh @@ -0,0 +1,6 @@ +#!/bin/sh +rm -rf static/frontends/pleroma-fe +FRONTEND_LINK=`curl -sS https://git.pleroma.social/pleroma/pleroma-fe/-/jobs/artifacts/develop/download?job=build | grep -io '