diff --git a/docker/netbird/docker-compose.yml b/docker/netbird/docker-compose.yml new file mode 100644 index 0000000..300be57 --- /dev/null +++ b/docker/netbird/docker-compose.yml @@ -0,0 +1,111 @@ +--- +services: + dashboard: + image: netbirdio/dashboard:latest + restart: unless-stopped + ports: + - 8005:80 + environment: + NETBIRD_MGMT_API_ENDPOINT: ${NETBIRD_MGMT_API_ENDPOINT:-https://vpn.fukurokuju.dev} + NETBIRD_MGMT_GRPC_API_ENDPOINT: ${NETBIRD_MGMT_GRPC_API_ENDPOINT:-https://vpn.fukurokuju.dev} + AUTH_AUDIENCE: ${NETBIRD_AUTH_AUDIENCE:-64e44b85ebdec2a3cf87c0c9916e2dbb0570f6d87b03ca8d149c3551565c3057ce1e559d16b5399cb7df60646e4e2bc6515842a198efb09d1620ea9ac1d8ace2} # yamllint disable rule:line-length + AUTH_CLIENT_ID: ${NETBIRD_AUTH_CLIENT_ID:-64e44b85ebdec2a3cf87c0c9916e2dbb0570f6d87b03ca8d149c3551565c3057ce1e559d16b5399cb7df60646e4e2bc6515842a198efb09d1620ea9ac1d8ace2} # yamllint disable rule:line-length + AUTH_AUTHORITY: ${NETBIRD_AUTH_AUTHORITY:-https://auth.fukurokuju.dev/application/o/netbird/} + USE_AUTH0: false + AUTH_SUPPORTED_SCOPES: ${NETBIRD_AUTH_SUPPORTED_SCOPES:-api offline_access openid email profile} + AUTH_REDIRECT_URI: + AUTH_SILENT_REDIRECT_URI: + NETBIRD_TOKEN_SOURCE: accessToken + NGINX_SSL_PORT: 443 + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + signal: + image: netbirdio/signal:latest + restart: unless-stopped + volumes: + - netbird-signal:/var/lib/netbird + ports: + - "10000:80" + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + relay: + image: netbirdio/relay:latest + restart: unless-stopped + environment: + NB_LOG_LEVEL: ${NB_LOG_LEVEL:-info} + NB_LISTEN_ADDRESS: ${NB_LISTEN_ADDRESS:-:33080} + NB_EXPOSED_ADDRESS: ${NB_EXPOSED_ADDRESS:-vpn.fukurokuju.dev:33080} + NB_AUTH_SECRET: ${NB_AUTH_SECRET} + ports: + - "33080:33080" + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + management: + image: netbirdio/management:latest + restart: unless-stopped + depends_on: + - dashboard + volumes: + - ${NETBIRD_MANAGEMENT_VOLUME:-/mnt/nas1/shared/netbird/management}/data:/var/lib/netbird + - ${NETBIRD_MANAGEMENT_VOLUME:-/mnt/nas1/shared/netbird/management}/management.json:/etc/netbird/management.json:z + ports: + - "33073:443" + command: [ + "--port", "443", + "--log-file", "console", + "--log-level", "info", + "--disable-anonymous-metrics=false", + "--single-account-mode-domain=vpn.fukurokuju.dev", + "--dns-domain=netbird.fuku", + ] + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + environment: + - NETBIRD_STORE_ENGINE_POSTGRES_DSN= + coturn: + image: coturn/coturn:latest + restart: unless-stopped + domainname: vpn.fukurokuju.dev + volumes: + - ${NETBIRD_COTURN_VOLUME:-/mnt/nas1/shared/netbird/coturn}/turnserver.conf:/etc/turnserver.conf:ro + network_mode: host + command: + - -c /etc/turnserver.conf + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + + peer-1: + image: netbirdio/netbird:0.29.2 + restart: unless-stopped + volumes: + - ${NETBIRD_PEER_VOLUME:-/mnt/nas1/shared/netbird/peer-1}/data:/etc/netbird + environment: + NB_MANAGEMENT_URL: https://vpn.fukurokuju.dev:443 + NB_SETUP_KEY: ${NB_SETUP_KEY} + cap_add: + - NET_ADMIN + depends_on: + - management + - dashboard + - relay + - signal + - coturn + +volumes: + netbird-mgmt: + netbird-signal: diff --git a/docker/netbird/sample.env b/docker/netbird/sample.env new file mode 100644 index 0000000..6a76871 --- /dev/null +++ b/docker/netbird/sample.env @@ -0,0 +1,2 @@ +NB_AUTH_SECRET= +NB_SETUP_KEY= diff --git a/tofu/authentik/main.tf b/tofu/authentik/main.tf index 97e82f1..758176a 100644 --- a/tofu/authentik/main.tf +++ b/tofu/authentik/main.tf @@ -27,6 +27,11 @@ resource "authentik_group" "admins" { is_superuser = true } +resource "authentik_group" "vpn" { + name = "vpn" + is_superuser = false +} + module "firezone" { source = "../modules/authentik-oidc" @@ -52,7 +57,7 @@ module "gitea" { app_access_group_id = "" redirect_uris = ["https://git.roboces.dev/user/oauth2/authentik/callback"] app_icon = "https://git.roboces.dev/assets/img/logo.svg" - app_description = "Beyond coding. We forge. " + app_description = "Beyond coding. We forge." app_publisher = "Forgejo" app_url = "https://git.roboces.dev/user/oauth2/authentik" sub_mode = "hashed_user_id" @@ -136,3 +141,22 @@ module "lidarr" { internal_host_ssl_validation = false app_icon = "https://lidarr.audio/img/background/logo.png" } + +module "netbird" { + source = "../modules/authentik-oidc" + app_name = "netbird" + app_slug = "netbird" + client_id = var.netbird_client_id + client_secret = var.netbird_client_secret + client_type = "public" + app_access_group_id = authentik_group.vpn.id + redirect_uris = [ + "https://vpn.fukurokuju.dev", + "https://vpn.fukurokuju.dev.*", + "http://localhost:53000" + ] + sub_mode = "user_id" + extra_property_mappings = [ + "goauthentik.io/providers/oauth2/scope-authentik_api" + ] +} diff --git a/tofu/authentik/sample.env b/tofu/authentik/sample.env index a22dd70..52c3922 100644 --- a/tofu/authentik/sample.env +++ b/tofu/authentik/sample.env @@ -10,3 +10,5 @@ TF_VAR_portainer_client_id= TF_VAR_portainer_client_secret= TF_VAR_paperless_client_id= TF_VAR_paperless_client_secret= +TF_VAR_netbird_client_id= +TF_VAR_netbird_client_secret= diff --git a/tofu/authentik/vars.tf b/tofu/authentik/vars.tf index 1d883c6..c0f227e 100644 --- a/tofu/authentik/vars.tf +++ b/tofu/authentik/vars.tf @@ -1,4 +1,3 @@ - variable "firezone_client_id" { description = "Client ID" type = string @@ -48,3 +47,12 @@ variable "paperless_client_secret" { description = "Paperless client secret" type = string } + +variable "netbird_client_id" { + description = "Netbird client ID" + type = string +} +variable "netbird_client_secret" { + description = "Netbird client secret" + type = string +} diff --git a/tofu/modules/authentik-oidc/main.tf b/tofu/modules/authentik-oidc/main.tf index ef3bd14..7489ff0 100644 --- a/tofu/modules/authentik-oidc/main.tf +++ b/tofu/modules/authentik-oidc/main.tf @@ -18,25 +18,28 @@ data "authentik_flow" "default-authentication-flow" { data "authentik_property_mapping_provider_scope" "default-scopes" { - managed_list = [ + managed_list = concat([ "goauthentik.io/providers/oauth2/scope-email", "goauthentik.io/providers/oauth2/scope-openid", "goauthentik.io/providers/oauth2/scope-profile", "goauthentik.io/providers/oauth2/scope-offline_access", - ] + ], var.extra_property_mappings) } resource "authentik_provider_oauth2" "provider_oidc" { - name = var.app_name - client_id = var.client_id - client_secret = var.client_secret - authorization_flow = data.authentik_flow.default-authorization-flow.id - authentication_flow = data.authentik_flow.default-authentication-flow.id - redirect_uris = var.redirect_uris - property_mappings = data.authentik_property_mapping_provider_scope.default-scopes.ids - sub_mode = var.sub_mode - signing_key = var.oidc_signing_key + name = var.app_name + client_id = var.client_id + client_secret = var.client_secret + client_type = var.client_type + authorization_flow = data.authentik_flow.default-authorization-flow.id + authentication_flow = data.authentik_flow.default-authentication-flow.id + redirect_uris = var.redirect_uris + property_mappings = data.authentik_property_mapping_provider_scope.default-scopes.ids + sub_mode = var.sub_mode + signing_key = var.oidc_signing_key + access_code_validity = var.access_code_validity + access_token_validity = var.access_token_validity } diff --git a/tofu/modules/authentik-oidc/vars.tf b/tofu/modules/authentik-oidc/vars.tf index 4db3bbb..56796af 100644 --- a/tofu/modules/authentik-oidc/vars.tf +++ b/tofu/modules/authentik-oidc/vars.tf @@ -18,6 +18,16 @@ variable "client_secret" { type = string } +variable "client_type" { + type = string + default = "confidential" + + validation { + condition = contains(["confidential", "public"], var.client_type) + error_message = "client_type must be 'confidential' or 'public'" + } +} + variable "app_access_group_id" { description = "ID of a group which will have access to the app" type = string @@ -31,6 +41,11 @@ variable "redirect_uris" { variable "sub_mode" { type = string default = "user_username" + + validation { + condition = contains(["user_id", "user_username", "hashed_user_id"], var.sub_mode) + error_message = "sub_mode must be 'user_id', 'user_username' or 'hashed_user_id'" + } } variable "oidc_signing_key" { @@ -59,7 +74,23 @@ variable "app_publisher" { type = string default = "" } + variable "app_url" { type = string default = "" } + +variable "access_code_validity" { + type = string + default = "minutes=1" +} + +variable "access_token_validity" { + type = string + default = "minutes=10" +} + +variable "extra_property_mappings" { + type = list(string) + default = [] +}