Set up firezone
This commit is contained in:
parent
8d8052c5cc
commit
09b62faa4a
97
modules/cloud/firezone/default.nix
Normal file
97
modules/cloud/firezone/default.nix
Normal 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
26
modules/cloud/firezone/gen_env
Executable 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
|
|
@ -48,7 +48,7 @@ let
|
||||||
description = "The port that the service is listening on";
|
description = "The port that the service is listening on";
|
||||||
};
|
};
|
||||||
entrypoints = mkOption {
|
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" ];
|
default = [ "https" ];
|
||||||
description = "The entrypoints that will serve the host";
|
description = "The entrypoints that will serve the host";
|
||||||
};
|
};
|
||||||
|
@ -58,7 +58,7 @@ let
|
||||||
description = "The middlewares to be used with the host.";
|
description = "The middlewares to be used with the host.";
|
||||||
};
|
};
|
||||||
protocol = mkOption {
|
protocol = mkOption {
|
||||||
type = enum [ "http" "tcp" ];
|
type = enum [ "http" "tcp" "udp" ];
|
||||||
default = "http";
|
default = "http";
|
||||||
description = "The protocol of the router and service";
|
description = "The protocol of the router and service";
|
||||||
};
|
};
|
||||||
|
@ -82,18 +82,18 @@ let
|
||||||
# Turns a host configuration into dynamic traefik configuration
|
# Turns a host configuration into dynamic traefik configuration
|
||||||
hostToConfig = name: host: {
|
hostToConfig = name: host: {
|
||||||
"${host.protocol}" = {
|
"${host.protocol}" = {
|
||||||
routers."${name}-router" = {
|
routers."${name}-router" = (if (host.protocol != "udp") then {
|
||||||
rule = filterOfHost host;
|
rule = filterOfHost host;
|
||||||
entryPoints = host.entrypoints;
|
|
||||||
tls = { certResolver = "le"; } // (if host.protocol == "tcp" then { passthrough = if (host ? tlsPassthrough) then host.tlsPassthrough else true; } else { });
|
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";
|
service = "${name}-service";
|
||||||
|
|
||||||
} // (
|
} // (
|
||||||
if host.protocol == "http" then
|
if host.protocol == "http" then
|
||||||
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; }
|
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; }
|
||||||
else if host.middlewares == [ ] then
|
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 = [
|
services."${name}-service".loadBalancer.servers = [
|
||||||
(
|
(
|
||||||
|
|
|
@ -61,6 +61,8 @@ in
|
||||||
entrypoints.imap.address = ":993";
|
entrypoints.imap.address = ":993";
|
||||||
entrypoints.smtp-submission.address = ":587";
|
entrypoints.smtp-submission.address = ":587";
|
||||||
entrypoints.smtp-submission-ssl.address = ":465";
|
entrypoints.smtp-submission-ssl.address = ":465";
|
||||||
|
## Wireguard
|
||||||
|
entrypoints.wireguard.address = ":51820/udp";
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
# -------
|
# -------
|
||||||
|
@ -84,5 +86,8 @@ in
|
||||||
|
|
||||||
# Set up firewall to allow traefik traffic.
|
# Set up firewall to allow traefik traffic.
|
||||||
config.networking.firewall.allowedTCPPorts = [ 80 443 993 587 465 ];
|
config.networking.firewall.allowedTCPPorts = [ 80 443 993 587 465 ];
|
||||||
config.networking.firewall.allowedUDPPorts = [ 443 ]; # QUIC
|
config.networking.firewall.allowedUDPPorts = [
|
||||||
|
443 # QUIC
|
||||||
|
51820 # Wireguard
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
# Set up cloud
|
# Set up cloud
|
||||||
../modules/cloud/authentik
|
../modules/cloud/authentik
|
||||||
|
../modules/cloud/firezone
|
||||||
../modules/cloud/postgresql
|
../modules/cloud/postgresql
|
||||||
../modules/cloud/traefik
|
../modules/cloud/traefik
|
||||||
../modules/cloud/bitwarden
|
../modules/cloud/bitwarden
|
||||||
|
@ -151,12 +152,29 @@
|
||||||
# Writefreely
|
# Writefreely
|
||||||
cloud.writefreely.enable = true;
|
cloud.writefreely.enable = true;
|
||||||
|
|
||||||
# Authentik (running under docker-compose T_T)
|
# Authentik
|
||||||
sops.secrets.authentik-env = { };
|
sops.secrets.authentik-env = { };
|
||||||
cloud.authentik.enable = true;
|
cloud.authentik.enable = true;
|
||||||
cloud.authentik.envFile = config.sops.secrets.authentik-env.path;
|
cloud.authentik.envFile = config.sops.secrets.authentik-env.path;
|
||||||
cloud.traefik.hosts.authentik = { host = "auth.dtth.ch"; port = config.cloud.authentik.port; };
|
cloud.traefik.hosts.authentik = { host = "auth.dtth.ch"; port = config.cloud.authentik.port; };
|
||||||
|
|
||||||
|
# Firezone
|
||||||
|
sops.secrets.firezone-env = { };
|
||||||
|
cloud.firezone.enable = true;
|
||||||
|
cloud.firezone.envFile = config.sops.secrets.firezone-env.path;
|
||||||
|
cloud.traefik.hosts.firezone = {
|
||||||
|
host = "vpn.dtth.ch";
|
||||||
|
port = config.cloud.firezone.httpPort;
|
||||||
|
localHost = "127.0.0.1";
|
||||||
|
};
|
||||||
|
cloud.traefik.hosts.firezone-vpn = {
|
||||||
|
host = "vpn.dtth.ch";
|
||||||
|
port = config.cloud.firezone.wireguardPort;
|
||||||
|
entrypoints = [ "wireguard" ];
|
||||||
|
protocol = "udp";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
# Outline
|
# Outline
|
||||||
sops.secrets.minio-secret-key = { };
|
sops.secrets.minio-secret-key = { };
|
||||||
sops.secrets.authentik-oidc-client-secret = { owner = "outline"; };
|
sops.secrets.authentik-oidc-client-secret = { owner = "outline"; };
|
||||||
|
|
|
@ -14,6 +14,7 @@ outline:
|
||||||
heisenbridge: ENC[AES256_GCM,data:rJY7gpcOY8nODR3KlYW1rEs54mKxr+AjNBeg1/2vTG0Gzpuvjgbnn5UVJS+P8uej/P4HfeFtlQSFZCEy8cXcwvwq97ppVliCGL4GMLRWaFmop35feC8t2ovh79cy/vKC7drASeGvWYNUmGRjboPuKA8W5LARa0HVDPGDLIEMVgJfYry/YKR3gsGmLzU7Mx1yLO6M/EFOJQJc84bSuu+CPSZcyUVF4SSNBiaDU5/NazlqaA9KWL6Xzu1MD2LEYdEFkRfitNgYj2m2gLd9voyGV4cfaCqJvYjJPwuZeZUoqCpDnom2JoV29q/Yq/gmyumPgOvriGxLsYBqV14MaCcE6KXE2uLicD+I/5or1AxepVDVjG9NoSgho1HpLvpRhMSCeXLk9+U+ykH3QA+0M+VVu9pswMMVQifnTtXZRM6pWxOnRVAzGf2tGDo4jy36S7pHaRn7SJcrljjWLfwHuNiu7E2uZhMrkcCjnjcBA9Xrb3drDQYVHya7XcoD4wOBHBDvVZwhYkNdkS3oYkom8A==,iv:fO1onfon3EdSNC/LjN1aWxpHBYq5aa0F/h0V6gl88ac=,tag:NL9p2nhIlEqgOdvUDM19Dg==,type:str]
|
heisenbridge: ENC[AES256_GCM,data:rJY7gpcOY8nODR3KlYW1rEs54mKxr+AjNBeg1/2vTG0Gzpuvjgbnn5UVJS+P8uej/P4HfeFtlQSFZCEy8cXcwvwq97ppVliCGL4GMLRWaFmop35feC8t2ovh79cy/vKC7drASeGvWYNUmGRjboPuKA8W5LARa0HVDPGDLIEMVgJfYry/YKR3gsGmLzU7Mx1yLO6M/EFOJQJc84bSuu+CPSZcyUVF4SSNBiaDU5/NazlqaA9KWL6Xzu1MD2LEYdEFkRfitNgYj2m2gLd9voyGV4cfaCqJvYjJPwuZeZUoqCpDnom2JoV29q/Yq/gmyumPgOvriGxLsYBqV14MaCcE6KXE2uLicD+I/5or1AxepVDVjG9NoSgho1HpLvpRhMSCeXLk9+U+ykH3QA+0M+VVu9pswMMVQifnTtXZRM6pWxOnRVAzGf2tGDo4jy36S7pHaRn7SJcrljjWLfwHuNiu7E2uZhMrkcCjnjcBA9Xrb3drDQYVHya7XcoD4wOBHBDvVZwhYkNdkS3oYkom8A==,iv:fO1onfon3EdSNC/LjN1aWxpHBYq5aa0F/h0V6gl88ac=,tag:NL9p2nhIlEqgOdvUDM19Dg==,type:str]
|
||||||
matrix-discord-bridge: ENC[AES256_GCM,data:/rlSjD6inKfak7HKKghH5ays5RjKmb9czGsoIOYHyTZC4A5EMucCbfn8DL1gkYXgvRHJ+QglGX/BGo5ebaxSj6nF60+aW87UG31KggOt5kkMuWsPsjvrufoc5IlNfWnXIWmqf8cdC01hmHEp7biUpI8CcfEZiD9OkOxbZcRfYqW+ttnzplFniRBjGPVZfL5g4DBbuJen5MuOrrMDo5CT+78n,iv:r9VBbDCAAElisCaDehrB6PhJHsaaHjdrk3103lmBT7o=,tag:WoNMMfyMifsL56yWq3MUOg==,type:str]
|
matrix-discord-bridge: ENC[AES256_GCM,data:/rlSjD6inKfak7HKKghH5ays5RjKmb9czGsoIOYHyTZC4A5EMucCbfn8DL1gkYXgvRHJ+QglGX/BGo5ebaxSj6nF60+aW87UG31KggOt5kkMuWsPsjvrufoc5IlNfWnXIWmqf8cdC01hmHEp7biUpI8CcfEZiD9OkOxbZcRfYqW+ttnzplFniRBjGPVZfL5g4DBbuJen5MuOrrMDo5CT+78n,iv:r9VBbDCAAElisCaDehrB6PhJHsaaHjdrk3103lmBT7o=,tag:WoNMMfyMifsL56yWq3MUOg==,type:str]
|
||||||
authentik-env: ENC[AES256_GCM,data:CjxTaqIcpBX7ea9L3tgJDELr8HBPJdxXsrOfhsiH4cXwCEzktsNKHjF7l95ZFgI5O08q4Vlbln5Dg4xPEx33nwUesEbQrT5d+n+2YaAxmm/WInrYzF+jB7HYTXASb3rY9PWgd2C3v+YPBkJetHlTUc/k19Q7lOQRNw==,iv:cG8Bi2eCsS+v94tSJBsqp+bjVLzXZvvwX1QVVSYExL8=,tag:VmbfcxCcfi3IpKjg3f8QPw==,type:str]
|
authentik-env: ENC[AES256_GCM,data:CjxTaqIcpBX7ea9L3tgJDELr8HBPJdxXsrOfhsiH4cXwCEzktsNKHjF7l95ZFgI5O08q4Vlbln5Dg4xPEx33nwUesEbQrT5d+n+2YaAxmm/WInrYzF+jB7HYTXASb3rY9PWgd2C3v+YPBkJetHlTUc/k19Q7lOQRNw==,iv:cG8Bi2eCsS+v94tSJBsqp+bjVLzXZvvwX1QVVSYExL8=,tag:VmbfcxCcfi3IpKjg3f8QPw==,type:str]
|
||||||
|
firezone-env: ENC[AES256_GCM,data:D83cSNjwtoZ8wVXTHoqclHGFfydhwKyna7q1LMhHGS2nieF2Yg9vWDSDqrlKy7NklKNqgQ9rzZwdAmnSrFDiO7y4Le1N5vsLcPrL7JmIjS6yyh5tpMw4jjZkwEvwtSx+9hI6ec5beE9vOGceO0hCmN8zr0Tt6Wr8gUGrvMACF8mkFSatbowZi4RGvCEOjnPue66LQXGbVcAZX8jP7/UuIiqujiVsOI0xa1VwbpeAtQ9Pu+9JuMycpR7OcnXv2ImRZYGYYL1Fd/peXYIrwZiASYb4Yx3TsC88I4br+dVATicsP/k0O8FZCRL53CIogt44thAy8a/Gba1k9By92agLUlnJ0EUBB17JoQ/Ad8MQuR/F4s39ANAqztMig9oRfQBuNXb0HrBHBAGfgXLCzTw3wK/jiGwpQF5EMapT7jsZJFEFRIQLgI/uXaiuDtqd1evUljmtRwF35+8iqx1Jid+fM/kJ+aqx2B244L/8kEeRxqewY2eL0K7Tr+2LP0YQVsNFmvN6eY7DiA4m4jYBDlzUsBSRBIfj8oEvQML/STmmf4YqB8bPVQEEtKFwdRooDPqdozTGpaZlkEjAemUvI+xxe/8ZDq44uPswN154389gDRWO3fGPKmeRHx9HkMH8/6kMHiUnYnooqGnQ3SQdp+4v,iv:N0XBePOw2DYzN/GSBlza+sa3KwAZOrjavB++zrmqMAg=,tag:z0BA512TIgIxtQ4z40Zatg==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
|
@ -47,8 +48,8 @@ sops:
|
||||||
by9kZFlTRVdCZFkxYTVVb0RIRk8zUlkKCqMw9oL9RaYBV5Hhy3o8Nm5xmGrPH8Sd
|
by9kZFlTRVdCZFkxYTVVb0RIRk8zUlkKCqMw9oL9RaYBV5Hhy3o8Nm5xmGrPH8Sd
|
||||||
hv36sxRFFNZT/DCKaHaSRbT3mfpBZSTXJt1dgl4nZe6whH54t/1KmA==
|
hv36sxRFFNZT/DCKaHaSRbT3mfpBZSTXJt1dgl4nZe6whH54t/1KmA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2023-04-26T19:50:09Z"
|
lastmodified: "2023-04-26T22:43:56Z"
|
||||||
mac: ENC[AES256_GCM,data:QSS+gJoTtSwaB/seeo4QHEjdmzQ+qdYwmDtKWKV44KZnudHQuNYTlklKBC7gzLncOIaoPgQ04ZSlL/J4RSI4gLLrNuf+DkxX8OSIOv44U8ynBP/yWObgCPz8XjS38Jl9ovhLAPXYb6GK3DGl4q01ghXSpvfVsjCpz8W7SAVkVSA=,iv:Po0fPtu+gznmPalCm77RG3WloTKtRIEHLAec5lTYvaE=,tag:ulfUHDy1UAmj6d/R4kO42A==,type:str]
|
mac: ENC[AES256_GCM,data:dWWck84crzDOwD8SlMjWarWn1ObcV4m7HJiS3+rpKdvjl4jYS5Nq5CXHwIY3YCsq63nelqLEjo8koas1wlEq4JsSYNpM1jVX5tjQia8wPjue6F5RNJdamfuQcctNEfqS4Wxo9HaxgpWrdRzpvTHzWfUjVn1UGGTnGArx8YeMQQ8=,iv:7CVQ01GQOPoqSkTi/o8XksOctGMpUJN06SxJy/nk88U=,tag:xDQoA8gQVt1mUFIj0k1aig==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.7.3
|
version: 3.7.3
|
||||||
|
|
Loading…
Reference in a new issue