Commit b9bbbf1f authored by Alex Castaño's avatar Alex Castaño

Remove unused stuff

parent 4bd464e8
# This file contains the configuration for Credo and you are probably reading
# this after creating it with `mix credo.gen.config`.
# If you find anything wrong or unclear in this file, please report an
# issue on GitHub:
# You can have as many configs as you like in the `configs:` field.
configs: [
# Run any config using `mix credo -C <name>`. If no config name is given
# "default" is used.
name: "default",
# These are the files included in the analysis:
files: %{
# You can give explicit globs or simply directories.
# In the latter case `**/*.{ex,exs}` will be used.
included: ["lib/", "src/", "web/", "apps/"],
excluded: [~r"/_build/", ~r"/deps/"]
# If you create your own checks, you must specify the source files for
# them here, so they can be loaded by Credo before running the analysis.
requires: [],
# Credo automatically checks for updates, like e.g. Hex does.
# You can disable this behaviour below:
check_for_updates: true,
# If you want to enforce a style guide and need a more traditional linting
# experience, you can change `strict` to `true` below:
strict: false,
# If you want to use uncolored output by default, you can change `color`
# to `false` below:
color: true,
# You can customize the parameters of any check by adding a second element
# to the tuple.
# To disable a check put `false` as second element:
# {Credo.Check.Design.DuplicatedCode, false}
checks: [
# For some checks, like AliasUsage, you can only customize the priority
# Priority values are: `low, normal, high, higher`
{Credo.Check.Design.AliasUsage, priority: :low},
# For others you can set parameters
# If you don't want the `setup` and `test` macro calls in ExUnit tests
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`.
{Credo.Check.Design.DuplicatedCode, excluded_macros: []},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
{Credo.Check.Design.TagTODO, exit_status: 2},
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 100},
{Credo.Check.Readability.ModuleDoc, false},
# Controversial and experimental checks (opt-in, just remove `, false`)
{Credo.Check.Refactor.ABCSize, false},
{Credo.Check.Refactor.AppendSingleItem, false},
{Credo.Check.Refactor.VariableRebinding, false},
{Credo.Check.Warning.MapGetUnsafePass, false},
# Deprecated checks (these will be deleted after a grace period)
{Credo.Check.Readability.Specs, false},
{Credo.Check.Warning.NameRedeclarationByAssignment, false},
{Credo.Check.Warning.NameRedeclarationByCase, false},
{Credo.Check.Warning.NameRedeclarationByDef, false},
{Credo.Check.Warning.NameRedeclarationByFn, false},
# Custom checks can be created using `mix credo.gen.check`.
......@@ -123,62 +123,7 @@ There is a `Makefile` with two commands:
By default, CommonsPub listens on port 4000 (TCP), so you can access it on http://localhost:4000/ (if you are on the same machine). In case of an error it will restart automatically.
### Frontends
CommonsPub does not ship with a front-end, as each use case will likely have a customised client app, though compatibility between clients and not reinventing the wheel (such as sharing React.js components) is encouraged.
### As systemd service (with provided .service file)
[Not tested with system reboot yet!] You'll also want to set up the server to be run as a systemd service. Example .service file can be found in `installation/moodle_net.service` you can put it in `/etc/systemd/system/`.
Running: `service moodle_net start`
Logs can be watched by using `journalctl -fu moodle_net.service`
### Standalone/run by other means
Run `mix phx.server` in repository's root, it will output log into stdout/stderr
### Using an upstream proxy for federation
Add the following to your `dev.secret.exs` or `prod.secret.exs` if you want to proxify all http requests that the server makes to an upstream proxy server:
config :moodle_net, :http,
proxy_url: ""
This is useful for running the server inside Tor or i2p.
## Admin Tasks
If you're running with Docker, all the `mix` commands below should be preceded by `docker exec -it [name_of_commonspub_container]`. You can use your keyboard's tab key to autocomplete thhe container name, which may look something like `commonspub_commonspub_1`.
### Invite a User (when registrations are closed)
Run `mix generate_invite_token` and you will receive an URL which includes an invite code that one person can use to sign up.
### Register a User
Run `mix register_user <name> <nickname> <email> <bio> <password>`. The `name` appears on statuses, while the nickname corresponds to the user, e.g. `@nickname@instance.tld`
### Password reset
Run `mix generate_password_reset username` to generate a password reset link that you can then send to the user.
### Moderators
You can make users moderators. They will then be able to delete any post.
Run `mix set_moderator username [true|false]` to make user a moderator or not.
### Monitoring
You can use `iex -S mix run` to run the app in interactive mode and then enter `:observer.start()` to launch [Erlang's observer](, which among other things will show you an applications tree:
![Observer example](installation/threads_tree.png)
## Troubleshooting
### No incoming federation
Check that you correctly forward the "host" header to backend. It is needed to validate signatures.
# Configuring the server
In the `config/` directory, you will find the following relevant files:
......@@ -193,95 +138,3 @@ Instead, overload the settings by editing the following files:
* `dev.secret.exs`: custom additional configuration for `MIX_ENV=dev`
* `prod.secret.exs`: custom additional configuration for `MIX_ENV=prod`
## Uploads configuration
To configure where to upload files, and wether or not
you want to remove automatically EXIF data from pictures
being uploaded.
config :moodle_net, MoodleNet.Upload,
uploads: "uploads",
strip_exif: false
* `uploads`: where to put the uploaded files, relative to the app's main directory.
* `strip_exif`: whether or not to remove EXIF data from uploaded pics automatically.
This needs Imagemagick installed on the system ( apt install imagemagick ).
## Block functionality
config :moodle_net, :activitypub,
accept_blocks: true,
unfollow_blocked: true,
outgoing_blocks: true
config :moodle_net, :user, deny_follow_blocked: true
* `accept_blocks`: whether to accept incoming block activities from
other instances
* `unfollow_blocked`: whether blocks result in people getting
* `outgoing_blocks`: whether to federate blocks to other instances
* `deny_follow_blocked`: whether to disallow following an account that
has blocked the user in question
## Message Rewrite Filters (MRFs)
Modify incoming and outgoing posts.
config :moodle_net, :instance,
rewrite_policy: MoodleNet.Web.ActivityPub.MRF.NoOpPolicy
`rewrite_policy` specifies which MRF policies to apply.
It can either be a single policy or a list of policies.
Currently, MRFs availible by default are:
* `MoodleNet.Web.ActivityPub.MRF.NoOpPolicy`
* `MoodleNet.Web.ActivityPub.MRF.DropPolicy`
* `MoodleNet.Web.ActivityPub.MRF.SimplePolicy`
* `MoodleNet.Web.ActivityPub.MRF.RejectNonPublic`
Some policies, such as SimplePolicy and RejectNonPublic,
can be additionally configured in their respective sections.
### NoOpPolicy
Does not modify posts (this is the default `rewrite_policy`)
### DropPolicy
Drops all posts.
It generally does not make sense to use this in production.
### SimplePolicy
Restricts the visibility of posts from certain instances.
config :moodle_net, :mrf_simple,
media_removal: [],
media_nsfw: [],
federated_timeline_removal: [],
reject: [],
accept: []
* `media_removal`: posts from these instances will have attachments
* `media_nsfw`: posts from these instances will have attachments marked
as nsfw
* `federated_timeline_removal`: posts from these instances will be
marked as unlisted
* `reject`: posts from these instances will be dropped
* `accept`: if not empty, only posts from these instances will be accepted
### RejectNonPublic
Drops posts with non-public visibility settings.
config :moodle_net :mrf_rejectnonpublic
allow_followersonly: false,
allow_direct: false,
* `allow_followersonly`: whether to allow follower-only posts through
the filter
* `allow_direct`: whether to allow direct messages through the filter
......@@ -8,24 +8,6 @@ use Mix.Config
# General application configuration
config :moodle_net, ecto_repos: [MoodleNet.Repo]
# config :moodle_net, MoodleNet.Repo, types: MoodleNet.PostgresTypes, adapter: Ecto.Adapters.Postgres
config :moodle_net, MoodleNet.Upload,
uploader: MoodleNet.Uploaders.Local,
strip_exif: false
config :moodle_net, MoodleNet.Uploaders.Local,
uploads: "uploads",
uploads_url: "{{base_url}}/media/{{file}}"
config :moodle_net, MoodleNet.Uploaders.S3,
bucket: nil,
public_endpoint: ""
config :moodle_net, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"]
config :moodle_net, :uri_schemes, additionnal_schemes: []
# Configures the endpoint
config :moodle_net, MoodleNetWeb.Endpoint,
url: [host: "localhost"],
......@@ -45,8 +27,6 @@ config :mime, :types, %{
"application/ld+json" => ["json"]
config :moodle_net, :httpoison, MoodleNet.HTTP
config :moodle_net, MoodleNet.Mailer,
adapter: Bamboo.LocalAdapter,
open_email_in_browser_url: "http://localhost:4000/sent_emails" # optional
......@@ -65,50 +45,7 @@ config :moodle_net, :instance,
version: version,
name: "Pub of the Commons",
email: "example@example.local",
description: "A Pub of the Commons instance, a generic fediverse server",
limit: 5000,
upload_limit: 16_000_000,
registrations_open: true,
rewrite_policy: ActivityPubWeb.MRF.NoOpPolicy,
public: true,
quarantined_instances: [],
managed_config: true
config :moodle_net, :fe,
theme: "moodle_net-dark",
logo: "/static/logo.png",
background: "/static/bg.jpg",
redirect_root_no_login: "/registration",
logo_mask: true,
logo_margin: "0.1em",
redirect_root_login: "/main/friends",
show_instance_panel: true,
scope_options_enabled: false,
collapse_message_with_subject: false
config :moodle_net, :activitypub,
accept_blocks: true,
unfollow_blocked: true,
outgoing_blocks: true
config :moodle_net, :user, deny_follow_blocked: true
config :moodle_net, :mrf_rejectnonpublic,
allow_followersonly: false,
allow_direct: false
config :moodle_net, :mrf_simple,
media_removal: [],
media_nsfw: [],
federated_timeline_removal: [],
reject: [],
accept: []
config :moodle_net, :media_proxy,
enabled: false,
redirect_on_failure: true
# base_url: ""
description: "A Pub of the Commons instance, a generic fediverse server"
config :phoenix, :format_encoders, json: Jason
config :phoenix, :json_library, Jason
......@@ -116,14 +53,6 @@ config :phoenix, :json_library, Jason
config :furlex, Furlex.Oembed,
oembed_host: ""
config :moodle_net, :suggestions,
enabled: false,
timeout: 300_000,
limit: 23,
web: "{{host}}+{{user}}"
config :moodle_net, MoodleNetWeb.Gettext, default_locale: "en", locales: ~w(en es)
# Import environment specific config. This must remain at the bottom
......@@ -10,8 +10,6 @@ config :moodle_net, MoodleNetWeb.Endpoint,
config :logger, level: :warn
# config :logger, level: :debug
config :moodle_net, MoodleNet.Upload, uploads: "test/uploads"
# Configure your database
config :moodle_net, MoodleNet.Repo,
adapter: Ecto.Adapters.Postgres,
......@@ -24,8 +22,6 @@ config :moodle_net, MoodleNet.Repo,
# Reduce hash rounds for testing
config :pbkdf2_elixir, rounds: 1
config :moodle_net, :httpoison, HTTPoison
config :phoenix_integration,
endpoint: MoodleNetWeb.Endpoint
social.domain.tld {
log /var/log/caddy/pleroma_access.log
errors /var/log/caddy/pleroma_error.log
proxy / localhost:4000 {
tls user@domain.tld {
# Remove the rest of the lines in here, if you want to support older devices
key_type p256
header / {
X-XSS-Protection "1; mode=block"
X-Frame-Options "DENY"
X-Content-Type-Options "nosniff"
Referrer-Policy "same-origin"
Strict-Transport-Security "max-age=31536000; includeSubDomains;"
Expect-CT "enforce, max-age=2592000"
Content-Security-Policy "default-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://social.domain.tld; upgrade-insecure-requests;"
# If you do not want remote frontends to be able to access your Pleroma backend server, remove these lines.
# If you want to allow all origins access, remove the origin lines.
# To use this directive, you need the http.cors plugin for Caddy.
cors / {
origin https://halcyon.domain.tld
origin https://pinafore.domain.tld
allowed_headers Authorization,Content-Type,Idempotency-Key
exposed_headers Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id
# Stop removing lines here.
# If you do not want to use the mediaproxy function, remove these lines.
# To use this directive, you need the http.cache plugin for Caddy.
cache {
match_path /proxy
default_max_age 720m
# Stop removing lines here.
# Requires OpenRC >= 0.35
export PORT=4000
export MIX_ENV=prod
# Ask process to terminate within 30 seconds, otherwise kill it
retry="SIGTERM/30 SIGKILL/5"
depend() {
need nginx postgresql
\ No newline at end of file
#Example configuration for when Apache httpd and Pleroma are on the same host.
#Needed modules: headers proxy proxy_http proxy_wstunnel rewrite ssl
#This assumes a Debian style Apache config. Put this in /etc/apache2/sites-available
#Install your TLS certificate, possibly using Let's Encrypt.
#Replace '' with your instance's domain wherever it appears
ServerTokens Prod
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<VirtualHost *:80>
Redirect permanent /
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/
SSLCertificateKeyFile /etc/letsencrypt/live/
SSLCertificateChainFile /etc/letsencrypt/live/
# Mozilla modern configuration, tweak to your needs
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off
Header always set X-Xss-Protection "1; mode=block"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy same-origin
Header always set Content-Security-Policy "default-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://pleroma.example.tld; upgrade-insecure-requests;"
# Uncomment this only after you get HTTPS working.
# Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /(.*) ws://localhost:4000/$1 [P,L]
ProxyRequests off
ProxyPass / http://localhost:4000/
ProxyPassReverse / http://localhost:4000/
RequestHeader set Host ""
ProxyPreserveHost On
# OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
\ No newline at end of file
# default nginx site config for Pleroma
# Simple installation instructions:
# 1. Install your TLS certificate, possibly using Let's Encrypt.
# 2. Replace 'example.tld' with your instance's domain wherever it appears.
# 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it
# in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx.
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g
inactive=720m use_temp_path=off;
server {
listen 80;
server_name example.tld;
return 301 https://$server_name$request_uri;
# Uncomment this if you need to use the 'webroot' method with certbot. Make sure
# that you also create the .well-known/acme-challenge directory structure in pleroma/priv/static and
# that is is accessible by the webserver. 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 <path to install>/pleroma/priv/static/;
# }
# Enable SSL session caching for improved performance
ssl_session_cache shared:ssl_session_cache:10m;
server {
listen 443 ssl http2;
ssl_session_timeout 5m;
ssl_trusted_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;
# Add TLSv1.0 to support older devices
ssl_protocols TLSv1.2;
# Uncomment line below if you want to support older devices (Before Android 4.4.2, IE 8, etc.)
# ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers on;
# 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;
server_name example.tld;
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;
location / {
# if you do not want remote frontends to be able to access your Pleroma backend
# server, remove these lines.
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always;
add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always;
if ($request_method = OPTIONS) {
return 204;
# stop removing lines here.
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "same-origin" always;
add_header X-Download-Options "noopen" always;
add_header Content-Security-Policy "default-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://example.tld; upgrade-insecure-requests;" always;
# Uncomment this only after you get HTTPS working.
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_pass http://localhost:4000;
client_max_body_size 16m;
location /proxy {
proxy_cache pleroma_media_cache;
proxy_cache_lock on;
proxy_ignore_client_abort on;
proxy_pass http://localhost:4000;
Description=Pleroma social network postgresql.service
ExecStart=/usr/local/bin/mix phx.server
ExecReload=/bin/kill $MAINPID
vcl 4.0;
import std;
backend default {
.host = "";
.port = "4000";
# ACL for IPs that are allowed to PURGE data from the cache
acl purge {
sub vcl_recv {
# Redirect HTTP to HTTPS
if (std.port(server.ip) != 443) {
set req.http.x-redir = "https://" + + req.url;
return (synth(750, ""));
# Pipe if WebSockets request is coming through
if (req.http.upgrade ~ "(?i)websocket") {
return (pipe);
# Allow purging of the cache
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return(synth(405,"Not allowed."));
# Pleroma MediaProxy - strip headers that will affect caching
if (req.url ~ "^/proxy/") {
unset req.http.Cookie;
unset req.http.Authorization;
unset req.http.Accept;
return (hash);
# Strip headers that will affect caching from all other static content
# This also permits caching of individual toots and AP Activities
if ((req.url ~ "^/(media|static)/") ||
(req.url ~ "(?i)\.(html|js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$"))
unset req.http.Cookie;
unset req.http.Authorization;
return (hash);
# Everything else should just be piped to Pleroma
return (pipe);
sub vcl_backend_response {
# gzip text content
if (beresp.http.content-type ~ "(text|text/css|application/x-javascript|application/javascript)") {
set beresp.do_gzip = true;
# etags are bad
unset beresp.http.etag;
# Don't cache objects that require authentication
if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") {
set beresp.uncacheable = true;
return (deliver);
# Default object caching of 86400s;
set beresp.ttl = 86400s;
# Allow serving cached content for 6h in case backend goes down
set beresp.grace = 6h;
# Do not cache 5xx responses
if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
set beresp.uncacheable = true;
return (abandon);