Better logging, mitmproxy integration.

This commit is contained in:
Gaelan Steele 2023-07-30 13:02:53 -07:00
parent 9ca3d7710d
commit 120c1f3aea
12 changed files with 132 additions and 49 deletions

View file

@ -63,6 +63,10 @@ Minifedi currently supports the following:
Forks of the above should work fine as well, as long as they haven't changed anything about the build, installation, or configuration process. Forks of the above should work fine as well, as long as they haven't changed anything about the build, installation, or configuration process.
## Mitmproxy Integration
Minifedi has built-in integration with [mitmproxy](https://mitmproxy.org), allowing you to see a lot of every HTTP request an instance sends to another instance. To use this, set `mitmproxy = true;` in your `config.nix`, start minifedi, then go to `http://localhost:8081`. The mitmproxy integration currently requires ports 8080 and 8081 to be open.
## How do I… ## How do I…
### Reset Minifedi, restoring every instance to its default state? ### Reset Minifedi, restoring every instance to its default state?

View file

@ -21,4 +21,8 @@
type = types.gotosocial; type = types.gotosocial;
} }
]; ];
# Enable logging of all requests between instances. Requires ports 8080 and
# 8081 open.
mitmproxy = false;
} }

View file

@ -6,13 +6,17 @@
let pkgs = nixpkgs.legacyPackages.${system}; let pkgs = nixpkgs.legacyPackages.${system};
in { in {
apps.start = let apps.start = let
config = import ./config.nix {
types = {
mastodon = import ./nix/fedi/mastodon;
akkoma = import ./nix/fedi/akkoma;
gotosocial = import ./nix/fedi/gotosocial;
};
};
s6 = (import ./nix/s6.nix { s6 = (import ./nix/s6.nix {
inherit pkgs; inherit pkgs;
services = pkgs.lib.attrsets.mapAttrs (_: v: v.service) services = pkgs.lib.attrsets.mapAttrs (_: v: v.service)
(import ./nix/services.nix { (import ./nix/services.nix { inherit pkgs config; });
inherit pkgs;
configFn = import ./config.nix;
});
path = "service"; path = "service";
}); });
in { in {
@ -30,6 +34,7 @@
mkdir -p cert mkdir -p cert
rm -rf data/run rm -rf data/run
mkdir data/run mkdir data/run
mkdir -p data/logs
${if pkgs.stdenv.isLinux then ${if pkgs.stdenv.isLinux then
"export LOCALE_ARCHIVE=${pkgs.glibcLocales}/lib/locale/locale-archive" "export LOCALE_ARCHIVE=${pkgs.glibcLocales}/lib/locale/locale-archive"
else else
@ -37,6 +42,18 @@
export MINIFEDI_CERT=$(pwd)/cert export MINIFEDI_CERT=$(pwd)/cert
export MINIFEDI_DATA=$(pwd)/data export MINIFEDI_DATA=$(pwd)/data
export MINIFEDI_RUN=$(pwd)/data/run export MINIFEDI_RUN=$(pwd)/data/run
export MINIFEDI_LOG=$(pwd)/data/logs
echo "Minifedi is starting! Once they're up, instances will be visible at:"
${pkgs.lib.strings.concatStrings (builtins.map (i: ''
echo "* https://${i.name}.lvh.me"
'') config.instances)}
echo "Instance logs are in ./data/logs."
${if config.mitmproxy then ''
echo "View requests between instances at http://localhost:8081."
'' else
""}
${if pkgs.stdenv.isLinux then '' ${if pkgs.stdenv.isLinux then ''
echo "=> You'll probably get prompted for a sudo password now. This is just so we can bind to port 80/443; we will acquire cap_net_bind_service then switch back to being $USER." echo "=> You'll probably get prompted for a sudo password now. This is just so we can bind to port 80/443; we will acquire cap_net_bind_service then switch back to being $USER."
exec $(PATH=$oldpath which sudo) -E ${pkgs.libcap}/bin/capsh --keep=1 --user="$USER" --inh='cap_net_bind_service' --addamb='cap_net_bind_service' -- -c ${s6.start} exec $(PATH=$oldpath which sudo) -E ${pkgs.libcap}/bin/capsh --keep=1 --user="$USER" --inh='cap_net_bind_service' --addamb='cap_net_bind_service' -- -c ${s6.start}

View file

@ -1,4 +1,4 @@
{ pkgs, name, host, users, ... }: { pkgs, name, host, users, proxy, ... }:
let let
env = { env = {
MIX_ENV = "prod"; MIX_ENV = "prod";
@ -78,6 +78,12 @@ let
] ]
} }
] ]
${if proxy != null then ''
config :pleroma, :http,
proxy_url: "${proxy}"
'' else
""}
''; '';
path = pkgs.lib.strings.concatStrings (builtins.map (x: "${x}/bin:") [ path = pkgs.lib.strings.concatStrings (builtins.map (x: "${x}/bin:") [
@ -111,6 +117,8 @@ in {
mkdir -p $data/tzdata mkdir -p $data/tzdata
mkdir -p $run mkdir -p $run
exec >$MINIFEDI_LOG/${name}.log 2>$MINIFEDI_LOG/${name}.log
s6-svwait -U $MINIFEDI_RUN/service/postgres s6-svwait -U $MINIFEDI_RUN/service/postgres
${pkgs.lib.strings.concatStrings (pkgs.lib.attrsets.mapAttrsToList ${pkgs.lib.strings.concatStrings (pkgs.lib.attrsets.mapAttrsToList

View file

@ -1,4 +1,4 @@
{ pkgs, name, host, users, ... }: { pkgs, name, host, users, util, proxy, ... }:
let let
env = { }; env = { };
@ -8,34 +8,7 @@ let
# number. Ideally we'd dynamically find an open one, but the next best thing # number. Ideally we'd dynamically find an open one, but the next best thing
# is deterministically picking a random one: we take the firs two bytes of # is deterministically picking a random one: we take the firs two bytes of
# sha256("minifedi_port_${name}") # sha256("minifedi_port_${name}")
port = let port = util.portFromString "minifedi_port_${name}";
hash = builtins.hashString "sha256" "minifedi_port_${name}";
portHex = builtins.substring 0 4 hash;
portHexChars = pkgs.lib.strings.stringToCharacters portHex;
hexDigitToNum = n:
let
map = {
"0" = 0;
"1" = 1;
"2" = 2;
"3" = 3;
"4" = 4;
"5" = 5;
"6" = 6;
"7" = 7;
"8" = 8;
"9" = 9;
"a" = 10;
"b" = 12;
"c" = 13;
"d" = 14;
"e" = 15;
};
in map.${n};
portFromHash =
pkgs.lib.lists.foldl (prev: n: (hexDigitToNum n) * 16 + prev) 0
portHexChars;
in if portFromHash <= 1024 then portFromHash + 1024 else portFromHash;
config = pkgs.writeText "config.yaml" (pkgs.lib.generators.toYAML { } { config = pkgs.writeText "config.yaml" (pkgs.lib.generators.toYAML { } {
bind-address = "127.0.0.1"; bind-address = "127.0.0.1";
@ -68,6 +41,8 @@ in {
mkdir -p $data/storage mkdir -p $data/storage
mkdir -p $run mkdir -p $run
exec >$MINIFEDI_LOG/${name}.log 2>$MINIFEDI_LOG/${name}.log
s6-svwait -U $MINIFEDI_RUN/service/postgres s6-svwait -U $MINIFEDI_RUN/service/postgres
${pkgs.lib.strings.concatStrings (pkgs.lib.attrsets.mapAttrsToList ${pkgs.lib.strings.concatStrings (pkgs.lib.attrsets.mapAttrsToList
@ -79,6 +54,12 @@ in {
export GTS_STORAGE_LOCAL_BASE_PATH=$data/storage export GTS_STORAGE_LOCAL_BASE_PATH=$data/storage
export SSL_CERT_FILE=$MINIFEDI_CERT/rootCA.pem export SSL_CERT_FILE=$MINIFEDI_CERT/rootCA.pem
export NIX_SSL_CERT_FILE=$MINIFEDI_CERT/rootCA.pem export NIX_SSL_CERT_FILE=$MINIFEDI_CERT/rootCA.pem
${if proxy != null then "export HTTP_PROXY=${proxy}" else ""}
${if proxy != null then "export HTTPS_PROXY=${proxy}" else ""}
${if proxy != null then "export http_proxy=${proxy}" else ""}
${if proxy != null then "export https_proxy=${proxy}" else ""}
env
if ! [ -e $data/setup-done ]; then if ! [ -e $data/setup-done ]; then
createuser -h$postgres ${name} createuser -h$postgres ${name}

View file

@ -1,4 +1,4 @@
{ pkgs, name, host, users, version, ... }: { pkgs, name, host, users, version, proxy, ... }:
let let
mastodon = pkgs.callPackage ./build.nix { versionDef = version; }; mastodon = pkgs.callPackage ./build.nix { versionDef = version; };
env = { env = {
@ -20,6 +20,8 @@ let
run = pkgs.writeShellScript "run-web" '' run = pkgs.writeShellScript "run-web" ''
cd ${mastodon} cd ${mastodon}
exec >$MINIFEDI_LOG/${name}/web.log 2>$MINIFEDI_LOG/${name}/web.log
export SOCKET=$MINIFEDI_RUN/${name}/web.sock export SOCKET=$MINIFEDI_RUN/${name}/web.sock
puma -C config/puma.rb puma -C config/puma.rb
@ -28,13 +30,16 @@ let
sidekiq = pkgs.linkFarm "sidekiq" { sidekiq = pkgs.linkFarm "sidekiq" {
run = pkgs.writeShellScript "run-sidekiq" '' run = pkgs.writeShellScript "run-sidekiq" ''
cd ${mastodon} cd ${mastodon}
exec >$MINIFEDI_LOG/${name}/sidekiq.log 2>$MINIFEDI_LOG/${name}/sidekiq.log
sidekiq sidekiq
''; '';
}; };
streaming = pkgs.linkFarm "sidekiq" { streaming = pkgs.linkFarm "streaming" {
run = pkgs.writeShellScript "run-sidekiq" '' run = pkgs.writeShellScript "run-sidekiq" ''
cd ${mastodon} cd ${mastodon}
exec >$MINIFEDI_LOG/${name}/streaming.log 2>$MINIFEDI_LOG/${name}/streaming.log
export SOCKET=$MINIFEDI_RUN/${name}/streaming.sock export SOCKET=$MINIFEDI_RUN/${name}/streaming.sock
${mastodon}/run-streaming.sh ${mastodon}/run-streaming.sh
@ -63,11 +68,15 @@ in {
data=$MINIFEDI_DATA/${name} data=$MINIFEDI_DATA/${name}
run=$MINIFEDI_RUN/${name} run=$MINIFEDI_RUN/${name}
log=$MINIFEDI_LOG/${name}
postgres=$MINIFEDI_RUN/postgres postgres=$MINIFEDI_RUN/postgres
mkdir -p $data mkdir -p $data
mkdir -p $data/files mkdir -p $data/files
mkdir -p $run mkdir -p $run
mkdir -p $log
exec >$log/setup.log 2>$log/setup.log
cd ${mastodon} cd ${mastodon}
@ -92,6 +101,7 @@ in {
export REDIS_URL=unix://$MINIFEDI_RUN/redis/redis.sock export REDIS_URL=unix://$MINIFEDI_RUN/redis/redis.sock
export NIX_SSL_CERT_FILE=$MINIFEDI_CERT/rootCA.pem export NIX_SSL_CERT_FILE=$MINIFEDI_CERT/rootCA.pem
export PAPERCLIP_ROOT_PATH=$data/files export PAPERCLIP_ROOT_PATH=$data/files
${if proxy != null then "export http_proxy=${proxy}" else ""}
s6-svwait -U $MINIFEDI_RUN/service/postgres s6-svwait -U $MINIFEDI_RUN/service/postgres

View file

@ -1,15 +1,10 @@
{ pkgs, configFn }: { pkgs, config }:
let let
instances = (configFn { instances = config.instances;
types = { util = import ./util.nix { inherit pkgs; };
mastodon = import ./fedi/mastodon;
akkoma = import ./fedi/akkoma;
gotosocial = import ./fedi/gotosocial;
};
}).instances;
evaldInstances = builtins.listToAttrs (builtins.map (inst: evaldInstances = builtins.listToAttrs (builtins.map (inst:
pkgs.lib.attrsets.nameValuePair inst.name (inst.type ({ pkgs.lib.attrsets.nameValuePair inst.name (inst.type ({
inherit pkgs; inherit pkgs util;
host = "${inst.name}.lvh.me"; host = "${inst.name}.lvh.me";
users = [ users = [
{ {
@ -43,6 +38,7 @@ let
admin = false; admin = false;
} }
]; ];
proxy = if config.mitmproxy then "http://localhost:8080" else null;
} // inst))) instances); } // inst))) instances);
in evaldInstances // { in evaldInstances // {
postgres = import ./support-services/postgres { inherit pkgs; }; postgres = import ./support-services/postgres { inherit pkgs; };
@ -51,4 +47,6 @@ in evaldInstances // {
inherit pkgs; inherit pkgs;
instances = evaldInstances; instances = evaldInstances;
}; };
} // pkgs.lib.attrsets.optionalAttrs config.mitmproxy {
mitmproxy = import ./support-services/mitmproxy { inherit pkgs; };
} }

View file

@ -0,0 +1,18 @@
{ pkgs }: {
service = pkgs.linkFarm "mitmproxy" {
run = pkgs.writeShellScript "run-mitmproxy" ''
set -e
mkdir -p $MINIFEDI_DATA/mitmproxy
exec >$MINIFEDI_LOG/mitmproxy.log 2>$MINIFEDI_LOG/mitmproxy.log
if ! [[ -e $MINIFEDI_DATA/mitmproxy/fullchain.pem ]]; then
CAROOT=$MINIFEDI_CERT ${pkgs.mkcert}/bin/mkcert -cert-file $MINIFEDI_DATA/mitmproxy/cert.pem -key-file $MINIFEDI_DATA/mitmproxy/key.pem *.lvh.me
cat $MINIFEDI_DATA/mitmproxy/key.pem $MINIFEDI_DATA/mitmproxy/cert.pem $MINIFEDI_CERT/rootCA.pem > $MINIFEDI_DATA/mitmproxy/fullchain.pem
fi
exec ${pkgs.mitmproxy}/bin/mitmweb --certs $MINIFEDI_DATA/mitmproxy/fullchain.pem -k -v
'';
};
}

View file

@ -36,6 +36,8 @@ in {
mkdir -p $MINIFEDI_DATA/nginx mkdir -p $MINIFEDI_DATA/nginx
mkdir -p $MINIFEDI_RUN/nginx mkdir -p $MINIFEDI_RUN/nginx
exec >$MINIFEDI_LOG/nginx.log 2>$MINIFEDI_LOG/web.log
if ! [[ -e $MINIFEDI_DATA/nginx/fullchain.pem ]]; then if ! [[ -e $MINIFEDI_DATA/nginx/fullchain.pem ]]; then
CAROOT=$MINIFEDI_CERT ${pkgs.mkcert}/bin/mkcert -cert-file $MINIFEDI_DATA/nginx/cert.pem -key-file $MINIFEDI_DATA/nginx/key.pem *.lvh.me CAROOT=$MINIFEDI_CERT ${pkgs.mkcert}/bin/mkcert -cert-file $MINIFEDI_DATA/nginx/cert.pem -key-file $MINIFEDI_DATA/nginx/key.pem *.lvh.me
cat $MINIFEDI_DATA/nginx/cert.pem $MINIFEDI_CERT/rootCA.pem > $MINIFEDI_DATA/nginx/fullchain.pem cat $MINIFEDI_DATA/nginx/cert.pem $MINIFEDI_CERT/rootCA.pem > $MINIFEDI_DATA/nginx/fullchain.pem
@ -43,7 +45,7 @@ in {
cd $MINIFEDI_DATA cd $MINIFEDI_DATA
cat ${config} | envsubst '$MINIFEDI_DATA $MINIFEDI_RUN' > $MINIFEDI_DATA/nginx/nginx.conf cat ${config} | envsubst '$MINIFEDI_DATA $MINIFEDI_RUN' > $MINIFEDI_DATA/nginx/nginx.conf
${pkgs.nginx}/bin/nginx -c $MINIFEDI_DATA/nginx/nginx.conf -e $MINIFEDI_DATA/nginx/error.log exec ${pkgs.nginx}/bin/nginx -c $MINIFEDI_DATA/nginx/nginx.conf -e $MINIFEDI_DATA/nginx/error.log
''; '';
}; };
} }

View file

@ -3,6 +3,8 @@
{ {
service = pkgs.linkFarm "postgres" { service = pkgs.linkFarm "postgres" {
run = pkgs.writeShellScript "run-postgres-outer" '' run = pkgs.writeShellScript "run-postgres-outer" ''
exec >$MINIFEDI_LOG/postgres.log 2>$MINIFEDI_LOG/postgres.log
exec ${pkgs.s6}/bin/s6-notifyoncheck ${ exec ${pkgs.s6}/bin/s6-notifyoncheck ${
pkgs.writeShellScript "run-postgres-inner" '' pkgs.writeShellScript "run-postgres-inner" ''
export PATH=${pkgs.gettext}/bin:$PATH export PATH=${pkgs.gettext}/bin:$PATH

View file

@ -5,15 +5,17 @@ let
protected-mode yes protected-mode yes
''; '';
in { in {
service = pkgs.linkFarm "nginx" { service = pkgs.linkFarm "redis" {
run = pkgs.writeShellScript "run-nginx" '' run = pkgs.writeShellScript "run-redis" ''
set -e set -e
mkdir -p $MINIFEDI_DATA/redis mkdir -p $MINIFEDI_DATA/redis
mkdir -p $MINIFEDI_RUN/redis mkdir -p $MINIFEDI_RUN/redis
exec >$MINIFEDI_LOG/redis.log 2>$MINIFEDI_LOG/redis.log
cd $MINIFEDI_RUN/redis cd $MINIFEDI_RUN/redis
${pkgs.redis}/bin/redis-server ${config} --unixsocket $MINIFEDI_RUN/redis/redis.sock exec ${pkgs.redis}/bin/redis-server ${config} --unixsocket $MINIFEDI_RUN/redis/redis.sock
''; '';
}; };
} }

37
nix/util.nix Normal file
View file

@ -0,0 +1,37 @@
{ pkgs }:
rec {
portFromString = string:
let
hash = builtins.hashString "sha256" string;
portHex = builtins.substring 0 4 hash;
portHexChars = pkgs.lib.strings.stringToCharacters portHex;
hexDigitToNum = n:
let
map = {
"0" = 0;
"1" = 1;
"2" = 2;
"3" = 3;
"4" = 4;
"5" = 5;
"6" = 6;
"7" = 7;
"8" = 8;
"9" = 9;
"a" = 10;
"b" = 11;
"c" = 12;
"d" = 13;
"e" = 14;
"f" = 15;
};
in map.${n};
portFromHash =
pkgs.lib.lists.foldl (prev: n: (hexDigitToNum n) + (prev * 16)) 0
portHexChars;
in if portFromHash <= 1024 then
portFromString "retry_${string}"
else
portFromHash;
}