Set up firezone

This commit is contained in:
Natsu Kagami 2023-04-27 02:32:10 +02:00
parent 8d8052c5cc
commit 09b62faa4a
Signed by: nki
GPG key ID: 7306B3D3C3AD6E51
6 changed files with 157 additions and 10 deletions

View file

@ -0,0 +1,97 @@
{ pkgs, config, lib, ... }:
with lib;
let
cfg = config.cloud.firezone;
mkImage =
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage;
images = {
postgresql = mkImage {
imageName = "postgres";
finalImageTag = "15-alpine";
imageDigest = "sha256:07ec36ad2d5ab9250f38c8ef749239b662cf15d03c9ddb7167422edbbdf71156";
};
firezone = mkImage {
imageName = "firezone/firezone";
finalImageTag = "latest";
imageDigest = "sha256:76d869f322998432a09e3f3366f9f5908fe8b2f2968c80b4a60a1a78f879482f";
};
};
in
{
options.cloud.firezone = {
enable = mkEnableOption "Enable authentik OAuth server";
envFile = mkOption {
type = types.path;
description = "Path to an environment file that is generated by bin/gen_env";
};
httpPort = mkOption {
type = types.int;
description = "Exposed HTTP port";
default = 51880;
};
wireguardPort = mkOption {
type = types.int;
description = "Exposed Wireguard port";
default = 51821;
};
};
config = mkIf cfg.enable {
systemd.services.arion-firezone.serviceConfig.EnvironmentFile = cfg.envFile;
virtualisation.arion.projects.firezone.settings = {
services.postgres.service = {
image = images.postgresql;
restart = "unless-stopped";
healthcheck = {
test = [ "CMD-SHELL" "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}" ];
start_period = "20s";
interval = "30s";
retries = 5;
timeout = "5s";
};
volumes = [ "/var/lib/firezone/database:/var/lib/postgresql/data" ];
environment = {
POSTGRES_USER = "postgres";
POSTGRES_DB = "firezone";
POSTGRES_PASSWORD = "\${DATABASE_PASSWORD}";
};
networks = [ "firezone-network" ];
};
services.firezone.out.service.networks.firezone-network = {
ipv4_address = "172.25.0.100";
ipv6_address = "2001:3990:3990::99";
};
services.firezone.service = {
image = images.firezone;
restart = "unless-stopped";
volumes = [ "/var/lib/firezone/data:/var/firezone" ];
env_file = [ cfg.envFile ];
ports = [
"${toString cfg.httpPort}:13000"
"${toString cfg.wireguardPort}:51820/udp"
];
capabilities.NET_ADMIN = true;
capabilities.SYS_MODULE = true;
sysctls = {
"net.ipv6.conf.all.disable_ipv6" = 0;
"net.ipv4.ip_forward" = 1;
"net.ipv6.conf.all.forwarding" = 1;
};
depends_on = [ "postgres" ];
};
networks.firezone-network = {
enable_ipv6 = true;
driver = "bridge";
ipam.config = [
{ subnet = "172.25.0.0/16"; }
{ subnet = "2001:3990:3990::/64"; gateway = "2001:3990:3990::1"; }
];
};
};
};
}

26
modules/cloud/firezone/gen_env Executable file
View file

@ -0,0 +1,26 @@
#!/usr/bin/env sh
cat <<-EOF
VERSION=latest
EXTERNAL_URL=_CHANGE_ME_
DEFAULT_ADMIN_EMAIL=_CHANGE_ME_
DEFAULT_ADMIN_PASSWORD=$(openssl rand -base64 12)
GUARDIAN_SECRET_KEY=$(openssl rand -base64 48)
SECRET_KEY_BASE=$(openssl rand -base64 48)
LIVE_VIEW_SIGNING_SALT=$(openssl rand -base64 24)
COOKIE_SIGNING_SALT=$(openssl rand -base64 6)
COOKIE_ENCRYPTION_SALT=$(openssl rand -base64 6)
DATABASE_ENCRYPTION_KEY=$(openssl rand -base64 32)
DATABASE_PASSWORD=$(openssl rand -base64 12)
# The ability to change the IPv4 and IPv6 address pool will be removed
# in a future Firezone release in order to reduce the possible combinations
# of network configurations we need to handle.
#
# Due to the above, we recommend not changing these unless absolutely
# necessary.
WIREGUARD_IPV4_NETWORK=100.64.0.0/10
WIREGUARD_IPV4_ADDRESS=100.64.0.1
WIREGUARD_IPV6_NETWORK=fd00::/106
WIREGUARD_IPV6_ADDRESS=fd00::1
EOF

View file

@ -48,7 +48,7 @@ let
description = "The port that the service is listening on";
};
entrypoints = mkOption {
type = listOf (enum [ "http" "https" "smtp-submission" "smtp-submission-ssl" "imap" ]);
type = listOf (enum [ "http" "https" "smtp-submission" "smtp-submission-ssl" "imap" "wireguard" ]);
default = [ "https" ];
description = "The entrypoints that will serve the host";
};
@ -58,7 +58,7 @@ let
description = "The middlewares to be used with the host.";
};
protocol = mkOption {
type = enum [ "http" "tcp" ];
type = enum [ "http" "tcp" "udp" ];
default = "http";
description = "The protocol of the router and service";
};
@ -82,18 +82,18 @@ let
# Turns a host configuration into dynamic traefik configuration
hostToConfig = name: host: {
"${host.protocol}" = {
routers."${name}-router" = {
routers."${name}-router" = (if (host.protocol != "udp") then {
rule = filterOfHost host;
entryPoints = host.entrypoints;
tls = { certResolver = "le"; } // (if host.protocol == "tcp" then { passthrough = if (host ? tlsPassthrough) then host.tlsPassthrough else true; } else { });
} else { }) // {
entryPoints = host.entrypoints;
service = "${name}-service";
} // (
if host.protocol == "http" then
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; }
else if host.middlewares == [ ] then
{ }
else abort "Cannot have middlewares on tcp routers"
else abort "Cannot have middlewares on non-http routers"
);
services."${name}-service".loadBalancer.servers = [
(

View file

@ -61,6 +61,8 @@ in
entrypoints.imap.address = ":993";
entrypoints.smtp-submission.address = ":587";
entrypoints.smtp-submission-ssl.address = ":465";
## Wireguard
entrypoints.wireguard.address = ":51820/udp";
# Logging
# -------
@ -84,5 +86,8 @@ in
# Set up firewall to allow traefik traffic.
config.networking.firewall.allowedTCPPorts = [ 80 443 993 587 465 ];
config.networking.firewall.allowedUDPPorts = [ 443 ]; # QUIC
config.networking.firewall.allowedUDPPorts = [
443 # QUIC
51820 # Wireguard
];
}