Skip to content

Commit

Permalink
plausible, nixos/plausible: Default to listen on localhost.
Browse files Browse the repository at this point in the history
This is a safer default configuration, changing:

* the plausible HTTP web server
* the Erlang Beam VM inter-node RPC port
* the Erlang EPMD port

to be listening on localhost only.

This makes Plausible have a safe default configuration, like all other
networked services in NixOS

For background discussion, see: #130244
  • Loading branch information
nh2 committed Jul 16, 2021
1 parent 6de23b9 commit dac1687
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
77 changes: 77 additions & 0 deletions nixos/modules/services/web-apps/plausible.nix
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ in {
framework docs</link>.
'';
};
listenAddress = mkOption {
default = "127.0.0.1";
type = types.str;
description = ''
The IP address on which the server is listening.
When changing listen IPs, also consider
<option>services.plausible.erlang.vmListenAddress</option> and
<option>services.plausible.erlang.epmdListenAddress</option>.
'';
};
port = mkOption {
default = 8000;
type = types.port;
Expand All @@ -116,6 +127,34 @@ in {
};
};

erlang = {
vmListenAddress = mkOption {
default = "127.0.0.1";
type = types.str;
description = ''
The IP address on which Beam (Erlang VM) is listening for
inter-node communication. See
<link xlink:href="https://erlang.org/doc/man/kernel_app.html#configuration">
<literal>inet_dist_use_interface</literal>
</link>.
The value given here is a normal IP address; it is translated
to an Erlang IP address tuple by this module.
'';
};
epmdListenAddress = mkOption {
default = "127.0.0.1";
type = types.str;
description = ''
The IP address on which the Erlang Port Mapper Daemon
spawned by Plausible is listening on. See
<link xlink:href="https://erlang.org/doc/man/epmd.html#environment-variables">
<literal>ERL_EPMD_ADDRESS</literal>
</link>.
'';
};
};

mail = {
email = mkOption {
default = "hello@plausible.local";
Expand Down Expand Up @@ -205,6 +244,44 @@ in {
# Configuration options from
# https://plausible.io/docs/self-hosting-configuration
PORT = toString cfg.server.port;
LISTEN_IP = cfg.server.listenAddress;
# Elixir spwans the Erlang VM, which will listen by default on all
# interfaces for messages between Erlang nodes (capable of)
# remote code execution; it can be protected by a cookie; see
# https://erlang.org/doc/reference_manual/distributed.html#security).
# To restrict this to an interface of our choice (e.g. localhost
# or a VPN IP) we need to set `inet_dist_use_interface`,
# which accepts the IP address as an Erlang tuple.
RELEASE_VM_ARGS =
let
ip = cfg.erlang.vmListenAddress;
# Elixir script that turns an IP address into an Erlang address tuple,
# printing it to stdout, and failing on invalid parse.
# Also works on IPv6.
# Example: `127.0.0.1` -> `{127,0,0,1}`.
erlangAddressTupleCommand = pkgs.writeTextFile {
executable = true;
name = "ip-to-erlang-address-tuple.exs";
text = ''
#! ${pkgs.elixir}/bin/elixir
case :inet.parse_address('${ip}') do
{:ok, ip_addr} ->
IO.write(inspect(ip_addr))
{:error, reason} ->
IO.puts(:stderr, "Invalid IP address '#{'${ip}'}'; error: #{inspect(reason)}")
System.halt(1) # `halt()` terminates ~1 second faster than `stop()`
end
'';
};
in
pkgs.runCommand "plausible-vm-args" {} ''
set -eu -o pipefail
IP=$(${erlangAddressTupleCommand})
echo "-kernel inet_dist_use_interface \"$IP\"" > "$out"
'';
# Elixir also spawns EPMD; set its listen address.
ERL_EPMD_ADDRESS = cfg.erlang.epmdListenAddress;
DISABLE_REGISTRATION = boolToString cfg.server.disableRegistration;

RELEASE_TMP = "/var/lib/plausible/tmp";
Expand Down
8 changes: 8 additions & 0 deletions pkgs/servers/web-apps/plausible/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ beamPackages.mixRelease {
# Ensure that `tzdata` doesn't write into its store-path
# https://github.com/plausible/analytics/pull/1096, but rebased onto 1.3.0
./tzdata-rebased.patch

# Allow user to specify listen interface via LISTEN_IP.
# https://github.com/plausible/analytics/pull/1190, but rebased onto 1.3.0
(fetchpatch {
name = "plausible-Allow-user-to-specify-listen-interface-via-LISTEN_IP.patch";
url = "https://github.com/nh2/analytics/commit/63aa7f5206ba2459ff7d04a842fe3ed6663975bc.patch";
sha256 = "1lhlhipnsisb9cz5m28i120c0ffwcfjjrypvmjxivlh32lx8mhbx";
})
];

passthru = {
Expand Down

0 comments on commit dac1687

Please sign in to comment.