├── .envrc ├── .github ├── copilot-instructions.md ├── dependabot.yml └── workflows │ ├── dependabot-auto-merge.yml │ └── main.yml ├── .gitignore ├── .tool-versions ├── LICENSE ├── Makefile ├── README.md ├── build.sh ├── custom_theme_overrides ├── 404.html └── main.html ├── docs ├── .pages ├── README.md ├── assets │ ├── access-policy-1.png │ ├── access-policy-2.png │ ├── access-policy-3.png │ ├── attachment_color.png │ ├── clistart.gif │ ├── clusters.png │ ├── config-connector.png │ ├── elastic-kibana-banner.png │ ├── google-cloud-logging.png │ ├── google-secret-manager-env-label.png │ ├── google-secret-manager-env-value.png │ ├── google-secret-manager-example-env.png │ ├── google-secret-manager-example-single-value.png │ ├── google-secret-manager-region.png │ ├── google-secret-manager-secret-value.png │ ├── google-secret-manager-start.png │ ├── google-secret-manager-sync-label.png │ ├── grafana-add-logs-panel.png │ ├── grafana-logs-metrics.png │ ├── grafana-loki-banner.png │ ├── grafana-loki-query-builder.gif │ ├── grafana-new-dashboard-query.png │ ├── grafana-new-dashboard.png │ ├── grafana-tempo-logs.png │ ├── grafana-tempo-query-builder.png │ ├── grafana-tempo-trace-view.png │ ├── grafana-tempo.png │ ├── jira_secure_log.png │ ├── jita_portal.png │ ├── logo-white.png │ ├── logo.png │ ├── metrics_overview.png │ ├── nais-teams.png │ ├── nais-yaml.png │ ├── nais_army_knife.png │ ├── nais_xmas.svg │ ├── nais_xmas2.svg │ ├── naisdevice-dos-and-donts.svg │ ├── naisdevice-logo.svg │ ├── naisdevice-systray-icon.svg │ ├── navTunnel.png │ ├── postgres-observability-google.png │ ├── postgres-observability-grafana.png │ ├── postgres-observability-nais-console.png │ ├── resource-overview.svg │ ├── salsa-graph.png │ ├── salsa-login.png │ ├── salsa-team.png │ ├── sqlproxy.svg │ ├── team-logs-banner.png │ ├── tiered-storage.svg │ ├── tracing.png │ ├── zero-trust-1.png │ ├── zero-trust-2.png │ ├── zero-trust-3.png │ ├── zero-trust-4.png │ ├── zero-trust-5.png │ ├── zero-trust-6.png │ ├── zero-trust-7.png │ └── zones.png ├── auth │ ├── .pages │ ├── README.md │ ├── entra-id │ │ ├── .pages │ │ ├── README.md │ │ ├── explanations │ │ │ └── README.md │ │ ├── how-to │ │ │ ├── consume-m2m.md │ │ │ ├── consume-obo.md │ │ │ ├── generate.md │ │ │ ├── login.md │ │ │ └── secure.md │ │ ├── partials │ │ │ ├── .pages │ │ │ ├── app-access.md │ │ │ ├── user-access.md │ │ │ └── validate.md │ │ └── reference │ │ │ └── README.md │ ├── explanations │ │ └── README.md │ ├── how-to │ │ └── login.md │ ├── idporten │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ └── login.md │ │ └── reference │ │ │ └── README.md │ ├── maskinporten │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── .pages │ │ │ ├── consume.md │ │ │ ├── expose-fss-apps.md │ │ │ └── secure.md │ │ └── reference │ │ │ └── README.md │ ├── partials │ │ ├── .pages │ │ ├── texas-footer.md │ │ ├── texas-header.md │ │ ├── token-exchange.md │ │ ├── token.md │ │ ├── validate-manually.md │ │ └── validate.md │ ├── reference │ │ └── README.md │ └── tokenx │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ ├── consume.md │ │ ├── generate.md │ │ └── secure.md │ │ └── reference │ │ └── README.md ├── build │ ├── .pages │ ├── README.md │ ├── how-to │ │ ├── build-and-deploy.md │ │ ├── dependabot-auto-merge.md │ │ ├── templating.md │ │ ├── tracing.md │ │ └── use-image-outside-nais.md │ └── reference │ │ └── nais-deploy.md ├── css │ └── gcp_only_admonition.css ├── explanations │ ├── .pages │ ├── nais.md │ ├── team.md │ └── under-the-hood.md ├── legal │ ├── app-pvk.md │ ├── app-ros.md │ ├── arkivloven.md │ ├── dpa │ │ ├── README.md │ │ ├── aiven-dpa.md │ │ ├── azure-dpa.md │ │ └── gcp-dpa.md │ ├── nais-pvk.md │ ├── nais-ros.md │ └── roles-responsibilities.md ├── material_theme_stylesheet_overrides │ ├── grid.css │ └── uu.css ├── observability │ ├── .pages │ ├── README.md │ ├── alerting │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── grafana.md │ │ │ ├── prometheus-advanced.md │ │ │ └── prometheus-basic.md │ │ └── reference │ │ │ └── prometheusrule.md │ ├── frontend │ │ └── README.md │ ├── how-to │ │ └── auto-instrumentation.md │ ├── logging │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── access-secure-logs.md │ │ │ ├── audit-logs.md │ │ │ ├── disable.md │ │ │ ├── enable-secure-logs.md │ │ │ ├── kibana.md │ │ │ ├── kubectl.md │ │ │ ├── logs-in-dashboards.md │ │ │ ├── logs-metrics-alerts.md │ │ │ ├── loki.md │ │ │ └── team-logs.md │ │ └── reference │ │ │ ├── destinations.md │ │ │ ├── kql.md │ │ │ ├── logql.md │ │ │ ├── loki-labels.md │ │ │ └── loki-metrics.md │ ├── metrics │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── dashboard.md │ │ │ ├── expose.md │ │ │ ├── grafana-from-infoscreen.md │ │ │ └── push.md │ │ └── reference │ │ │ ├── globals.md │ │ │ ├── grafana.md │ │ │ ├── metrics.md │ │ │ ├── otel.md │ │ │ └── promql.md │ ├── reference │ │ ├── auto-config.md │ │ └── glossary.md │ └── tracing │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ ├── context-propagation.md │ │ ├── correlate-traces-logs.md │ │ ├── elastic-apm.md │ │ └── tempo.md │ │ └── reference │ │ ├── span-metrics.md │ │ ├── trace-semconv.md │ │ └── traceql.md ├── operate │ ├── .pages │ ├── README.md │ ├── cli │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── install.md │ │ │ └── troubleshooting.md │ │ └── reference │ │ │ ├── aiven.md │ │ │ ├── debug.md │ │ │ ├── device.md │ │ │ ├── kubeconfig.md │ │ │ ├── postgres.md │ │ │ └── validate.md │ ├── console.md │ ├── how-to │ │ ├── command-line-access.md │ │ └── create-team.md │ └── naisdevice │ │ ├── .pages │ │ ├── README.md │ │ ├── explanations │ │ ├── .pages │ │ └── jita.md │ │ └── how-to │ │ ├── .pages │ │ ├── install-kolide.md │ │ ├── install.md │ │ ├── troubleshooting.md │ │ ├── uninstall-kolide.md │ │ ├── uninstall.md │ │ └── update.md ├── persistence │ ├── .pages │ ├── README.md │ ├── bigquery │ │ ├── .pages │ │ ├── README.md │ │ └── how-to │ │ │ ├── connect.md │ │ │ └── create.md │ ├── buckets │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── create.md │ │ │ └── delete.md │ │ └── reference │ │ │ └── README.md │ ├── cloudsql │ │ ├── .pages │ │ ├── README.md │ │ ├── explanations │ │ │ ├── cloud-sql-credentials.md │ │ │ ├── cloud-sql-instance.md │ │ │ ├── cloud-sql-proxy.md │ │ │ ├── grants-and-privileges.md │ │ │ └── migrate-to-new-instance.md │ │ ├── how-to │ │ │ ├── additional-users.md │ │ │ ├── certification-sync-issues.md │ │ │ ├── change-tier.md │ │ │ ├── connect-to-cloned.md │ │ │ ├── database-observability.md │ │ │ ├── debugging.md │ │ │ ├── delete-database.md │ │ │ ├── enable-auditing.md │ │ │ ├── existing-instance-private-ip.md │ │ │ ├── migrate-to-new-instance.md │ │ │ ├── migrating-databases-to-gcp.md │ │ │ ├── password-sync-issues.md │ │ │ ├── personal-access.md │ │ │ ├── reset-database-credentials.md │ │ │ └── upgrade-postgres.md │ │ └── reference │ │ │ └── README.md │ ├── explanations │ │ └── responsibilities.md │ ├── kafka │ │ ├── .pages │ │ ├── README.md │ │ ├── explanations │ │ │ ├── offset.md │ │ │ └── tiered-storage.md │ │ ├── how-to │ │ │ ├── access-from-non-nais.md │ │ │ ├── access.md │ │ │ ├── create.md │ │ │ ├── delete.md │ │ │ ├── internal.md │ │ │ ├── manage-acl.md │ │ │ ├── remove-access.md │ │ │ ├── renew-credentials-for-non-nais.md │ │ │ ├── schema-operations.md │ │ │ ├── tiered-storage.md │ │ │ └── troubleshoot.md │ │ └── reference │ │ │ ├── environment-variables.md │ │ │ ├── kafka-topic-example.md │ │ │ ├── kafka-topic-spec.md │ │ │ ├── monitoring.md │ │ │ └── pools.md │ ├── opensearch │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── .pages │ │ │ ├── create-legacy.md │ │ │ ├── create.md │ │ │ ├── dashboard.md │ │ │ ├── delete.md │ │ │ ├── migrate-to-console.md │ │ │ ├── upgrade-major-version.md │ │ │ └── use-in-workload.md │ │ └── reference │ │ │ └── README.md │ ├── postgresql │ │ ├── .pages │ │ ├── README.md │ │ ├── explanations │ │ │ └── postgres-cluster.md │ │ ├── how-to │ │ │ ├── database-observability.md │ │ │ ├── debugging.md │ │ │ ├── delete-database.md │ │ │ └── upgrade-postgres.md │ │ └── reference │ │ │ └── README.md │ └── valkey │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ ├── .pages │ │ ├── create-explicit.md │ │ ├── create.md │ │ ├── delete.md │ │ ├── migrate-to-console.md │ │ └── use-in-workload.md │ │ └── reference │ │ └── README.md ├── services │ ├── .pages │ ├── README.md │ ├── antivirus.md │ ├── cdn │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── .pages │ │ │ ├── manage-assets.md │ │ │ └── upload-assets.md │ │ └── reference │ │ │ └── upload-assets.md │ ├── feature-toggling.md │ ├── leader-election │ │ ├── .pages │ │ ├── README.md │ │ └── how-to │ │ │ └── enable.md │ ├── secrets │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ │ ├── .pages │ │ │ ├── binary.md │ │ │ ├── console.md │ │ │ └── workload.md │ │ └── reference │ │ │ └── README.md │ └── vulnerabilities │ │ ├── .pages │ │ ├── README.md │ │ ├── how-to │ │ └── sbom.md │ │ └── reference │ │ └── README.md ├── tags.md ├── tutorials │ ├── .pages │ ├── README.md │ └── hello-nais.md └── workloads │ ├── .pages │ ├── README.md │ ├── application │ ├── .pages │ ├── README.md │ ├── explanations │ │ └── expose.md │ ├── how-to │ │ ├── create.md │ │ ├── delete.md │ │ ├── expose.md │ │ └── redirect.md │ └── reference │ │ ├── application-example.md │ │ ├── application-spec.md │ │ ├── automatic-scaling.md │ │ └── ingress.md │ ├── explanations │ ├── environment.md │ ├── good-practices.md │ ├── imagerepository.md │ ├── migrating-to-gcp.md │ ├── workload-image.md │ └── zero-trust.md │ ├── how-to │ ├── access-policies.md │ ├── communication.md │ ├── debugging.md │ ├── disable-readonly.md │ ├── override-user-group.md │ ├── troubleshooting.md │ └── upload-image.md │ ├── job │ ├── .pages │ ├── README.md │ ├── how-to │ │ ├── create.md │ │ └── delete.md │ └── reference │ │ ├── naisjob-example.md │ │ └── naisjob-spec.md │ └── reference │ ├── access-policies.md │ ├── container-security.md │ ├── default-variables.md │ ├── environments.md │ ├── json-schema.md │ └── webproxy.md ├── flake.lock ├── flake.nix ├── main.py ├── mkdocs.yml ├── poetry.lock └── pyproject.toml /.envrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Export all: 4 | # - (should be) .gitignored 5 | # - (potentially) secret environment variables 6 | # - from dotenv-formatted files w/names starting w/`.env` 7 | DOTENV_FILES="$(find . -maxdepth 1 -type f -name '.env*' -and -not -name '.envrc')" 8 | for file in ${DOTENV_FILES}; do 9 | dotenv "${file}" 10 | done 11 | export DOTENV_FILES 12 | 13 | if command -v nix-shell &>/dev/null; then 14 | use flake 15 | fi 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" # must be root (ref. docs) 5 | schedule: 6 | interval: "weekly" 7 | time: "09:00" 8 | day: "monday" 9 | groups: 10 | actions: 11 | patterns: 12 | - "*" 13 | - package-ecosystem: "pip" # poetry / pyproject 14 | directory: "/" 15 | schedule: 16 | interval: "weekly" 17 | time: "09:00" 18 | day: "monday" 19 | groups: 20 | pip: 21 | patterns: 22 | - "*" 23 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: pull_request 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }} 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@v2.4.0 16 | with: 17 | github-token: "${{ secrets.GITHUB_TOKEN }}" 18 | - name: Enable auto-merge for Dependabot PRs 19 | if: steps.metadata.outputs.update-type != 'version-update:semver-major' 20 | run: gh pr merge --auto --squash "$PR_URL" 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ / IDEA 2 | .idea 3 | *.iml 4 | 5 | # Mac OS shait 6 | .DS_Store 7 | 8 | # Vim 9 | *.swp 10 | 11 | # mkdocs output folder (which contains all the HTML) 12 | site/ 13 | .cache 14 | 15 | # Terraform 16 | .terraform/ 17 | 18 | # Git folder - for .dockerignore purposes 19 | .git/ 20 | 21 | __pycache__/ 22 | .direnv/ 23 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | poetry 2.0.0 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 NAV 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all install local 2 | SHELL := bash 3 | 4 | all: install local 5 | 6 | install: 7 | poetry install 8 | 9 | local: 10 | env TENANT=$(TENANT) NOT_TENANT=not-$(TENANT) poetry run mkdocs serve --dirty 11 | 12 | clean-build: 13 | env TENANT=$(TENANT) NOT_TENANT=not-$(TENANT) poetry run mkdocs build --clean 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Nais documentation 2 | 3 | See the [Nais handbook](https://handbook.nais.io/technical/doc-guidelines/) for a more detailed explanation of the documentation structure and how to contribute. 4 | 5 | ## Tools for working with tenants 6 | 7 | ### Warning about features not available in test-nais 8 | 9 | If a page should have a warning about not being available in test-nais, add the following near the top of the page: 10 | 11 | ```markdown 12 | <> 13 | ``` 14 | 15 | ### Exclude a full page from one or more tenants documentation 16 | 17 | Add the following to the frontmatter of the page: 18 | 19 | ```yaml 20 | conditional: [not-test-nais, not-nav] 21 | ``` 22 | 23 | ### Include a page only for one or more tenants 24 | 25 | Add the following to the frontmatter of the page: 26 | 27 | ```yaml 28 | conditional: [tenant, nav, ssb] 29 | ^^^^^^--- the keyword "tenant" is required to exclude all not mentioned 30 | ``` 31 | 32 | ## Local development 33 | 34 | ## 1. Install Poetry 35 | 36 | ```bash 37 | asdf plugin add poetry 38 | asdf install poetry latest 39 | ``` 40 | 41 | ## 2. Install dependencies 42 | 43 | ```bash 44 | make install 45 | ``` 46 | ## 3. Serve the documentation locally 47 | 48 | ```bash 49 | make local 50 | ``` 51 | 52 | ## 3a. Serve a tenant-specific version of the documentation 53 | 54 | ```bash 55 | TENANT=nav make local 56 | ``` 57 | 58 | ## 3b. Do a clean build of the documentation 59 | 60 | ```bash 61 | make clean-build 62 | ``` 63 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | set -e 3 | 4 | rm -rf ./out 5 | mkdir -p ./out 6 | 7 | for TENANT in $@; 8 | do 9 | TENANT="${TENANT}" NOT_TENANT="not-${TENANT}" poetry run mkdocs build --strict -d "out/${TENANT}" 10 | done 11 | -------------------------------------------------------------------------------- /custom_theme_overrides/404.html: -------------------------------------------------------------------------------- 1 | {% extends "main.html" %} 2 | 3 | 4 | {% block content %} 5 |

404 - Not found

6 | {% endblock %} 7 | 8 | {% block scripts %} 9 | {{ super() }} 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /custom_theme_overrides/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | -------------------------------------------------------------------------------- /docs/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - Home: README.md 3 | - explanations 4 | - tutorials 5 | - "": "" 6 | - workloads 7 | - build 8 | - auth 9 | - observability 10 | - persistence 11 | - Other services: services 12 | - "": "" 13 | - operate 14 | - "": "" 15 | - tags.md 16 | - ... 17 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Nais Developer Documentation 3 | hide: 4 | - feedback 5 | - footer 6 | - toc 7 | --- 8 | 9 | 14 | 15 | # :wave: **Welcome to the Nais developer documentation!** 16 | 17 | Here you'll find _explanations_[^1], _how-to guides_[^2], and _references_[^3] for all things Nais. 18 | 19 | ### :seedling: **New to Nais?** 20 | 21 | Start here to get an idea of the fundamentals. 22 | 23 |
24 | 25 | - :ok_hand: [**What is Nais?**](explanations/nais.md) 26 | - :student: [**Your first application; Hello Nais**](tutorials/hello-nais.md) 27 | 28 |
29 | 30 | ### :technologist: **Already familiar with Nais?** 31 | 32 | What can we help you with today? 33 | 34 |
35 | 36 | - :package: [**Run your code**](workloads/README.md) 37 | - :rocket: [**Build and deploy your code**](build/README.md) 38 | - :open_file_folder: [**Store your data**](persistence/README.md) 39 | - :closed_lock_with_key: [**Auth your users and workloads**](auth/README.md) 40 | - :telescope: [**Gain insight into your workloads**](observability/README.md) 41 | - :wrench: [**Manage your workloads and services**](operate/README.md) 42 | - :heavy_plus_sign: [**Explore the rest of Nais**](services/README.md) 43 | 44 |
45 | 46 | [^1]: :bulb: [_explanations_](tags.md#explanation) present higher-level concepts. Most useful when you want to understand how Nais works. 47 | [^2]: :dart: [_how-to guides_](tags.md#how-to) help you achieve a specific goal. Most useful when you're trying to get something done. 48 | [^3]: :books: [_references_](tags.md#reference) contain technical descriptions and specifications. Most useful when you need to look up details about a specific feature. 49 | -------------------------------------------------------------------------------- /docs/assets/access-policy-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/access-policy-1.png -------------------------------------------------------------------------------- /docs/assets/access-policy-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/access-policy-2.png -------------------------------------------------------------------------------- /docs/assets/access-policy-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/access-policy-3.png -------------------------------------------------------------------------------- /docs/assets/attachment_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/attachment_color.png -------------------------------------------------------------------------------- /docs/assets/clistart.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/clistart.gif -------------------------------------------------------------------------------- /docs/assets/clusters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/clusters.png -------------------------------------------------------------------------------- /docs/assets/config-connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/config-connector.png -------------------------------------------------------------------------------- /docs/assets/elastic-kibana-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/elastic-kibana-banner.png -------------------------------------------------------------------------------- /docs/assets/google-cloud-logging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-cloud-logging.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-env-label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-env-label.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-env-value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-env-value.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-example-env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-example-env.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-example-single-value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-example-single-value.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-region.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-region.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-secret-value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-secret-value.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-start.png -------------------------------------------------------------------------------- /docs/assets/google-secret-manager-sync-label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/google-secret-manager-sync-label.png -------------------------------------------------------------------------------- /docs/assets/grafana-add-logs-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-add-logs-panel.png -------------------------------------------------------------------------------- /docs/assets/grafana-logs-metrics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-logs-metrics.png -------------------------------------------------------------------------------- /docs/assets/grafana-loki-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-loki-banner.png -------------------------------------------------------------------------------- /docs/assets/grafana-loki-query-builder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-loki-query-builder.gif -------------------------------------------------------------------------------- /docs/assets/grafana-new-dashboard-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-new-dashboard-query.png -------------------------------------------------------------------------------- /docs/assets/grafana-new-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-new-dashboard.png -------------------------------------------------------------------------------- /docs/assets/grafana-tempo-logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-tempo-logs.png -------------------------------------------------------------------------------- /docs/assets/grafana-tempo-query-builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-tempo-query-builder.png -------------------------------------------------------------------------------- /docs/assets/grafana-tempo-trace-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-tempo-trace-view.png -------------------------------------------------------------------------------- /docs/assets/grafana-tempo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/grafana-tempo.png -------------------------------------------------------------------------------- /docs/assets/jira_secure_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/jira_secure_log.png -------------------------------------------------------------------------------- /docs/assets/jita_portal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/jita_portal.png -------------------------------------------------------------------------------- /docs/assets/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/logo-white.png -------------------------------------------------------------------------------- /docs/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/logo.png -------------------------------------------------------------------------------- /docs/assets/metrics_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/metrics_overview.png -------------------------------------------------------------------------------- /docs/assets/nais-teams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/nais-teams.png -------------------------------------------------------------------------------- /docs/assets/nais-yaml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/nais-yaml.png -------------------------------------------------------------------------------- /docs/assets/nais_army_knife.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/nais_army_knife.png -------------------------------------------------------------------------------- /docs/assets/navTunnel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/navTunnel.png -------------------------------------------------------------------------------- /docs/assets/postgres-observability-google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/postgres-observability-google.png -------------------------------------------------------------------------------- /docs/assets/postgres-observability-grafana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/postgres-observability-grafana.png -------------------------------------------------------------------------------- /docs/assets/postgres-observability-nais-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/postgres-observability-nais-console.png -------------------------------------------------------------------------------- /docs/assets/salsa-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/salsa-graph.png -------------------------------------------------------------------------------- /docs/assets/salsa-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/salsa-login.png -------------------------------------------------------------------------------- /docs/assets/salsa-team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/salsa-team.png -------------------------------------------------------------------------------- /docs/assets/team-logs-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/team-logs-banner.png -------------------------------------------------------------------------------- /docs/assets/tracing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/tracing.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-1.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-2.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-3.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-4.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-5.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-6.png -------------------------------------------------------------------------------- /docs/assets/zero-trust-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zero-trust-7.png -------------------------------------------------------------------------------- /docs/assets/zones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nais/doc/21d67b41382295f428fc2de99c6355cec4d74dba/docs/assets/zones.png -------------------------------------------------------------------------------- /docs/auth/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 💡 Explanations: explanations 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | - ... 7 | -------------------------------------------------------------------------------- /docs/auth/entra-id/.pages: -------------------------------------------------------------------------------- 1 | title: Entra ID 2 | conditional: [tenant, nav] 3 | nav: 4 | - README.md 5 | - 💡 Explanations: explanations 6 | - 🎯 How-To: how-to 7 | - 📚 Reference: reference 8 | - ... 9 | -------------------------------------------------------------------------------- /docs/auth/entra-id/how-to/consume-m2m.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [entra-id, azure-ad, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Consume internal API as an application 7 | 8 | This how-to guides you through the steps required to consume an API secured with [Entra ID](../README.md) as an application (or a machine user). 9 | This is also known as the _machine-to-machine (M2M)_ or _client credentials_ flow. 10 | 11 | ## Prerequisites 12 | 13 | - The API you're consuming has [granted access to your application](secure.md#grant-access-to-consumers) 14 | 15 | ## Configure your application 16 | 17 | Enable Entra ID in your application: 18 | 19 | ```yaml title="app.yaml" 20 | spec: 21 | azure: 22 | application: 23 | enabled: true 24 | ``` 25 | 26 | Depending on how you communicate with the API you're consuming, [configure the appropriate outbound access policies](../../../workloads/how-to/access-policies.md#outbound-access). 27 | 28 | ## Acquire token 29 | 30 | Now you can request a new token for the API that you want to consume. 31 | 32 | {% set identity_provider = 'azuread' %} 33 | {% set target = 'api://../.default' %} 34 | {% set target_description = 'The intended _audience_ (target API or recipient) of the new token.' %} 35 | {% include 'auth/partials/token.md' %} 36 | 37 | ## Consume API 38 | 39 | Once you have acquired a new token, you can finally consume the target API by using the token as a [Bearer token](../../explanations/README.md#bearer-token): 40 | 41 | ```http 42 | GET /resource HTTP/1.1 43 | 44 | Host: api.example.com 45 | Authorization: Bearer eyJraWQ... 46 | ``` 47 | 48 | ## Related pages 49 | 50 | :books: [Entra ID reference](../reference/README.md) 51 | -------------------------------------------------------------------------------- /docs/auth/entra-id/how-to/consume-obo.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [entra-id, azure-ad, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Consume internal API on behalf of an employee 7 | 8 | This how-to guides you through the steps required to consume an API secured with [Entra ID](../README.md) on behalf of an employee. 9 | This is also known as the _on-behalf-of (OBO)_ flow. 10 | 11 | ## Prerequisites 12 | 13 | - Your application receives requests with an employee subject token in the `Authorization` header. The application is either: 14 | - [a backend API secured with Entra ID](secure.md), or 15 | - [a backend-for-frontend that logs in employees](login.md) 16 | - The API you're consuming has [granted access to your application and employees](secure.md#grant-access-to-consumers) 17 | 18 | ## Configure your application 19 | 20 | Depending on how you communicate with the API you're consuming, [configure the appropriate outbound access policies](../../../workloads/how-to/access-policies.md#outbound-access). 21 | 22 | ## Exchange token 23 | 24 | Now you can exchange the employee's subject token for a new token, targeting the API that you want to consume. 25 | 26 | {% set identity_provider = 'azuread' %} 27 | {% set target = 'api://../.default' %} 28 | {% include 'auth/partials/token-exchange.md' %} 29 | 30 | ## Consume API 31 | 32 | Once you have acquired a new token, you can finally consume the target API by using the token as a [Bearer token](../../explanations/README.md#bearer-token): 33 | 34 | ```http 35 | GET /resource HTTP/1.1 36 | 37 | Host: api.example.com 38 | Authorization: Bearer eyJraWQ... 39 | ``` 40 | 41 | ## Related pages 42 | 43 | :books: [Entra ID reference](../reference/README.md) 44 | -------------------------------------------------------------------------------- /docs/auth/entra-id/how-to/secure.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [entra-id, azure-ad, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Secure your API with Entra ID 7 | 8 | This how-to guides you through the steps required to secure your API using [Entra ID](../README.md): 9 | 10 | ## Grant access to consumers 11 | 12 | Depending on who your consumers are, you must grant access to either applications, users, or both. 13 | 14 | ### Application access 15 | 16 | {% include 'auth/entra-id/partials/app-access.md' %} 17 | 18 | ### User access 19 | 20 | {% include 'auth/entra-id/partials/user-access.md' %} 21 | 22 | --- 23 | 24 | Now that you have granted access to your consumers, they can now acquire tokens that target your application, either: 25 | 26 | - [on behalf of an employee](consume-obo.md), or 27 | - [as an application](consume-m2m.md) 28 | 29 | You will need to validate these tokens in your application. 30 | 31 | ## Validate tokens 32 | 33 | Verify incoming requests from consumers by validating the [JWT Bearer token](../../explanations/README.md#bearer-token) in the `Authorization` header. 34 | 35 | {% include 'auth/entra-id/partials/validate.md' %} 36 | -------------------------------------------------------------------------------- /docs/auth/entra-id/partials/.pages: -------------------------------------------------------------------------------- 1 | hide: true 2 | -------------------------------------------------------------------------------- /docs/auth/entra-id/partials/app-access.md: -------------------------------------------------------------------------------- 1 | Consumer applications may request tokens from Entra ID that targets your API application. 2 | Before issuing a token, Entra ID will check that the consumer is authorized to access your API application. 3 | 4 | Consumers are not authorized by default. 5 | To authorize consumers, specify inbound access policies in your application's configuration: 6 | 7 | ```yaml title="app.yaml" hl_lines="8-15" 8 | spec: 9 | azure: 10 | application: 11 | enabled: true 12 | accessPolicy: 13 | inbound: 14 | rules: 15 | - application: app-a # same namespace and cluster 16 | 17 | - application: app-b # same cluster 18 | namespace: other-namespace 19 | 20 | - application: app-c 21 | namespace: other-namespace 22 | cluster: other-cluster 23 | ``` 24 | 25 | The above configuration authorizes the following applications: 26 | 27 | * application `app-a` running in the same namespace and same cluster as your application 28 | * application `app-b` running in the namespace `other-namespace` in the same cluster 29 | * application `app-c` running in the namespace `other-namespace` in the cluster `other-cluster` 30 | -------------------------------------------------------------------------------- /docs/auth/entra-id/partials/validate.md: -------------------------------------------------------------------------------- 1 | {% set identity_provider = 'azuread' %} 2 | {% set claims_reference = '../reference/README.md#claims' %} 3 | {% set token_validation_reference = '../reference/README.md#manual-token-validation' %} 4 | {% include 'auth/partials/validate.md' %} 5 | -------------------------------------------------------------------------------- /docs/auth/idporten/.pages: -------------------------------------------------------------------------------- 1 | title: ID-porten 2 | nav: 3 | - README.md 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | - ... 7 | conditional: [tenant, nav] 8 | -------------------------------------------------------------------------------- /docs/auth/idporten/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [auth, idporten, services, explanation] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # ID-porten 7 | 8 | <> 9 | 10 | [ID-porten](https://docs.digdir.no/docs/idporten/) is the standard authentication service used by Norwegian citizens to access public services. 11 | 12 | If you have a citizen-facing application that requires authentication, you will need to integrate with ID-porten. 13 | Nais simplifies this by providing a [login proxy](../explanations/README.md#login-proxy) with endpoints to easily handle login, logout, and user sessions. 14 | 15 | Your application is responsible for verifying that inbound requests have valid [tokens](../explanations/README.md#tokens). 16 | 17 | :dart: [**Learn how to log in citizens**](how-to/login.md) 18 | -------------------------------------------------------------------------------- /docs/auth/maskinporten/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | conditional: [tenant, nav] 7 | -------------------------------------------------------------------------------- /docs/auth/maskinporten/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [auth, maskinporten, services, explanation] 3 | description: > 4 | Enabling service-to-service authorization between organizations and businesses using Maskinporten. 5 | conditional: [tenant, nav] 6 | --- 7 | 8 | # Maskinporten 9 | 10 | [Maskinporten](https://docs.digdir.no/maskinporten_overordnet.html) is a service provided by DigDir used to authorize access to APIs between organizations or businesses. 11 | 12 | Nais provides support for declarative registration and configuration of Maskinporten resources. 13 | These cover two distinct use cases: 14 | 15 | ## Consume an API 16 | 17 | To consume an external API secured with Maskinporten, you'll need to acquire a [token](../explanations/README.md#tokens): 18 | 19 | ```mermaid 20 | graph LR 21 | Consumer["Application"] -- request token ---> Maskinporten 22 | Maskinporten -- issue new token ---> Consumer 23 | Consumer -- use token ---> API["External API"] 24 | ``` 25 | 26 | :dart: [**Learn how to consume an external API using Maskinporten**](how-to/consume.md) 27 | 28 | ## Secure your API 29 | 30 | To secure your API with Maskinporten, you'll need to define _permissions_ (also known as _scopes_) and grant consumers access to these. 31 | 32 | Once configured, your consumers can acquire a token from Maskinporten to [consume your API](#consume-an-api). 33 | 34 | Your application code must verify inbound requests by validating the included tokens. 35 | 36 | :dart: [**Learn how to secure your API with Maskinporten**](how-to/secure.md) 37 | -------------------------------------------------------------------------------- /docs/auth/maskinporten/how-to/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - consume.md 3 | - secure.md 4 | - ... 5 | conditional: [tenant, nav] 6 | -------------------------------------------------------------------------------- /docs/auth/partials/.pages: -------------------------------------------------------------------------------- 1 | hide: true 2 | -------------------------------------------------------------------------------- /docs/auth/partials/texas-footer.md: -------------------------------------------------------------------------------- 1 | ```json title="Successful response" 2 | { 3 | "access_token": "eyJra...", 4 | "expires_in": 3599, 5 | "token_type": "Bearer" 6 | } 7 | ``` 8 | 9 | Your application does not need to validate this token. 10 | 11 | !!! info "Tokens are automatically cached by default" 12 | 13 | The endpoint will always return a cached token, if available. 14 | The endpoint will never return an expired token. 15 | 16 | To forcibly get a new token, set the `skip_cache` property to `true` in the request. 17 | This is only necessary if the token is denied by the target API, for example if permissions have changed since the token was issued. 18 | -------------------------------------------------------------------------------- /docs/auth/partials/texas-header.md: -------------------------------------------------------------------------------- 1 | Send a HTTP POST request to the endpoint found in the `<>` environment variable. 2 | The request must have a `Content-Type` header set to either: 3 | 4 | - `application/json` or 5 | - `application/x-www-form-urlencoded` 6 | 7 | The body of the request should contain the following parameters: 8 | -------------------------------------------------------------------------------- /docs/auth/partials/token-exchange.md: -------------------------------------------------------------------------------- 1 | {% set endpoint_env_var = 'NAIS_TOKEN_EXCHANGE_ENDPOINT' %} 2 | {% include 'auth/partials/texas-header.md' %} 3 | 4 | | Parameter | Example Value | Description | 5 | |:--------------------|:------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------| 6 | | `identity_provider` | `<>` | Always `<>`. | 7 | | `target` | `<>` | The intended _audience_ (target API or recipient) of the new token. | 8 | | `user_token` | `eyJra...` | The user's access token from the inbound request. Token that should be exchanged. | 9 | 10 | === "application/json" 11 | 12 | ```http title="Token request" 13 | POST ${<>} HTTP/1.1 14 | Content-Type: application/json 15 | 16 | { 17 | "identity_provider": "<>", 18 | "target": "<>", 19 | "user_token": "eyJra..." 20 | } 21 | ``` 22 | 23 | === "application/x-www-form-urlencoded" 24 | 25 | ```http title="Token request" 26 | POST ${<>} HTTP/1.1 27 | Content-Type: application/x-www-form-urlencoded 28 | 29 | identity_provider=<>& 30 | target=<>& 31 | user_token=eyJra... 32 | ``` 33 | 34 | {% include 'auth/partials/texas-footer.md' %} 35 | -------------------------------------------------------------------------------- /docs/auth/partials/token.md: -------------------------------------------------------------------------------- 1 | {% set endpoint_env_var = 'NAIS_TOKEN_ENDPOINT' %} 2 | {% include 'auth/partials/texas-header.md' %} 3 | 4 | | Parameter | Example Value | Description | 5 | |:--------------------|:------------------------|:--------------------------------| 6 | | `identity_provider` | `<>` | Always `<>`. | 7 | | `target` | `<>` | <> | 8 | 9 | {% if additional_parameters %} 10 | <> 11 | {% endif %} 12 | 13 | === "application/json" 14 | 15 | ```http title="Token request" 16 | POST ${<>} HTTP/1.1 17 | Content-Type: application/json 18 | 19 | { 20 | "identity_provider": "<>", 21 | "target": "<>" 22 | } 23 | ``` 24 | 25 | === "application/x-www-form-urlencoded" 26 | 27 | ```http title="Token request" 28 | POST ${<>} HTTP/1.1 29 | Content-Type: application/x-www-form-urlencoded 30 | 31 | identity_provider=<>& 32 | target=<> 33 | ``` 34 | 35 | {% include 'auth/partials/texas-footer.md' %} 36 | -------------------------------------------------------------------------------- /docs/auth/partials/validate-manually.md: -------------------------------------------------------------------------------- 1 | While we recommend using [the `NAIS_TOKEN_INTROSPECTION_ENDPOINT` endpoint for validating tokens](#runtime-variables-credentials), 2 | you can alternatively validate tokens natively within your application. 3 | 4 | Manual validation can be useful if you want to avoid the small overhead of an additional network call 5 | and rather depend on a native library within your ecosystem of choice. 6 | You should be familiar with the [auth concepts](../../explanations/README.md). 7 | 8 | Validating a JWT involves a number of steps. 9 | These steps are outlined and described below in a language- and framework-agnostic way. 10 | 11 | !!! tip "Libraries for token validation" 12 | 13 | We recommend using a library in your language of choice to handle all the validation steps described below. 14 | Here are some recommended libraries: 15 | 16 | - [navikt/oasis](https://github.com/navikt/oasis) (JavaScript) 17 | - [navikt/token-support](https://github.com/navikt/token-support) (Java / Kotlin) 18 | 19 | Validation is also supported by many popular frameworks: 20 | 21 | - [Ktor](https://ktor.io/docs/server-jwt.html) (Kotlin) 22 | - [Spring Security](https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html) (Java / Kotlin) 23 | 24 | To validate the token, start by validating the [signature and standard time-related claims](../../explanations/README.md#token-validation). 25 | 26 | Additionally, perform the following validations: 27 | -------------------------------------------------------------------------------- /docs/auth/tokenx/.pages: -------------------------------------------------------------------------------- 1 | title: TokenX 2 | conditional: [tenant, nav] 3 | nav: 4 | - README.md 5 | - 🎯 How-To: how-to 6 | - 📚 Reference: reference 7 | - ... 8 | -------------------------------------------------------------------------------- /docs/auth/tokenx/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [auth, tokenx, services, explanation] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # TokenX 7 | 8 | TokenX is Nais' own implementation of OAuth 2.0 Token Exchange. 9 | 10 | This allows internal applications to act on behalf of a citizen that originally authenticated with [ID-porten](../idporten/README.md), 11 | while maintaining the [zero trust](../../workloads/explanations/zero-trust.md) security model between applications throughout a request chain. 12 | 13 | Nais provides support for declarative registration and configuration of TokenX resources. 14 | These cover two distinct use cases: 15 | 16 | ## Consume an API 17 | 18 | To consume an API secured with TokenX on behalf of a citizen, you'll need to exchange their [token](../explanations/README.md#tokens) for a new token. 19 | 20 | The new token preserves the citizen's identity context and is only valid for the specific API you want to access. 21 | 22 | ```mermaid 23 | graph LR 24 | Consumer["User / Consumer API"] -- "`request with 25 | citizen token`" --> Application[Your app] 26 | Application -- "`exchange 27 | citizen token`" ---> TokenX 28 | TokenX -- "`issue new token 29 | for Other API`" ---> Application 30 | Application -- use new token ---> Other["Other API"] 31 | ``` 32 | 33 | :dart: [**Learn how to consume an internal API on behalf of a citizen**](how-to/consume.md) 34 | 35 | ## Secure your API 36 | 37 | To secure your API with TokenX, you'll need to grant consumers access to your application. 38 | 39 | Once configured, your consumers can exchange a token with TokenX to [consume your API](#consume-an-api). 40 | 41 | Your application code must verify inbound requests by validating the included tokens. 42 | 43 | :dart: [**Learn how to secure your API with TokenX**](how-to/secure.md) 44 | 45 | ## Generate a token for development 46 | 47 | In some cases, you want to locally develop and test against a secured API in the development environments. 48 | You will need a token to access said API. 49 | 50 | :dart: [**Learn how to generate a token for development**](how-to/generate.md) 51 | -------------------------------------------------------------------------------- /docs/auth/tokenx/how-to/consume.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [tokenx, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Consume internal API on behalf of a citizen 7 | 8 | This how-to guides you through the steps required to consume an API secured with [TokenX](../README.md): 9 | 10 | ## Prerequisites 11 | 12 | - Your application receives requests with a citizen subject token in the `Authorization` header 13 | - The subject token can either be from [ID-porten](../../idporten/README.md) or from TokenX itself 14 | - The API you're consuming has [granted access to your application](secure.md#grant-access-to-consumers) 15 | 16 | ## Configure your application 17 | 18 | Enable TokenX in your application: 19 | 20 | ```yaml title="app.yaml" 21 | spec: 22 | tokenx: 23 | enabled: true 24 | ``` 25 | 26 | Depending on how you communicate with the API you're consuming, [configure the appropriate outbound access policies](../../../workloads/how-to/access-policies.md#outbound-access). 27 | 28 | ## Exchange token 29 | 30 | {% set identity_provider = 'tokenx' %} 31 | {% set target = '::' %} 32 | {% include 'auth/partials/token-exchange.md' %} 33 | 34 | ## Consume API 35 | 36 | Once you have acquired a new token, you can finally consume the target API by using the token as a [Bearer token](../../explanations/README.md#bearer-token): 37 | 38 | ```http 39 | GET /resource HTTP/1.1 40 | 41 | Host: api.example.com 42 | Authorization: Bearer eyJraWQ... 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/auth/tokenx/how-to/secure.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [tokenx, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Secure your API with TokenX 7 | 8 | This how-to guides you through the steps required to secure your API using [TokenX](../README.md): 9 | 10 | ## Grant access to consumers 11 | 12 | Specify inbound access policies to authorize your consumers: 13 | 14 | ```yaml title="app.yaml" 15 | spec: 16 | tokenx: 17 | enabled: true 18 | accessPolicy: 19 | inbound: 20 | rules: 21 | - application: app-1 # same namespace and cluster 22 | 23 | - application: app-2 # same cluster 24 | namespace: team-a 25 | 26 | - application: app-3 27 | namespace: team-b 28 | cluster: prod-gcp 29 | ``` 30 | 31 | The above configuration authorizes the following applications: 32 | 33 | * application `app-1` running in the same namespace and same cluster as your application 34 | * application `app-2` running in the namespace `team-a` in the same cluster 35 | * application `app-3` running in the namespace `team-b` in the cluster `prod-gcp` 36 | 37 | Now that you have granted access to your consumers, they can now exchange tokens for new tokens that target your application. 38 | You will need to validate these tokens in your application. 39 | 40 | ## Validate tokens 41 | 42 | Verify incoming requests from consumers by validating the [JWT Bearer token](../../explanations/README.md#bearer-token) in the `Authorization` header. 43 | 44 | {% set identity_provider = 'tokenx' %} 45 | {% set claims_reference = '../reference/README.md#claims' %} 46 | {% set token_validation_reference = '../reference/README.md#manual-token-validation' %} 47 | {% include 'auth/partials/validate.md' %} 48 | -------------------------------------------------------------------------------- /docs/build/.pages: -------------------------------------------------------------------------------- 1 | title: Build and deploy 2 | nav: 3 | - README.md 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | - ... 7 | -------------------------------------------------------------------------------- /docs/build/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [build, deploy, explanation, services] 3 | --- 4 | 5 | # Build and deploy 6 | 7 | To make your application available to others, you need to build and deploy it. 8 | 9 | Nais attempts to make this as simple as possible by providing a set of composable [GitHub Actions](https://docs.github.com/en/actions). 10 | 11 | Use these actions to compose your own build and deploy pipeline through [Github Actions workflows](https://docs.github.com/en/actions/using-workflows). 12 | 13 | ## GitHub Actions 14 | 15 | :books: [nais/docker-build-push](https://github.com/nais/docker-build-push) 16 | 17 | :books: [nais/deploy](https://github.com/nais/deploy/tree/master/actions/deploy) 18 | 19 | See the respective GitHub Action links for detailed configuration options. 20 | 21 | ## What's next 22 | 23 | :dart: [Build and deploy with Github Actions](how-to/build-and-deploy.md) 24 | 25 | :dart: [Set up auto-merge with Dependabot](how-to/dependabot-auto-merge.md) 26 | -------------------------------------------------------------------------------- /docs/build/how-to/tracing.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [build, deploy, tracing, how-to] 3 | --- 4 | 5 | # Set up tracing for your pipeline 6 | 7 | To further support [DORA metrics](https://dora.dev/guides/dora-metrics-four-keys/) we use [tracing](../../observability/tracing/README.md) directly in the build pipeline. 8 | This will allow you to measure the time it takes for your team to deliver new code to production. 9 | 10 | !!! note "Lead time" 11 | 12 | > The amount of _time_ it takes a _commit_ to get into _production_ 13 | 14 | With these metrics you can also get a better view if changes to your pipeline affect the lead time for change. 15 | 16 | Nais automatically collects telemetry data from your pipeline when you use the 17 | `docker-build-push` action to build your Docker image. 18 | 19 | The following manual step is required on your part to visualize that data in Grafana; 20 | you must export the `TELEMETRY` environment variable when you deploy. 21 | 22 | !!! note ".github/workflows/main.yml" 23 | 24 | ```yaml hl_lines="7 11" 25 | jobs: 26 | build_and_deploy: 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Build and push Docker image 30 | uses: nais/docker-build-push@v0 31 | id: docker-build-push # make sure this ID matches the step id below 32 | - name: Deploy to Nais 33 | uses: nais/deploy/actions/deploy@v2 34 | env: 35 | TELEMETRY: ${{ steps.docker-build-push.outputs.telemetry }} 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/css/gcp_only_admonition.css: -------------------------------------------------------------------------------- 1 | .md-typeset .admonition.gcp-only, 2 | .md-typeset details.gcp-only { 3 | border-color: rgb(255, 128, 0); /* #ff9100 */ 4 | } 5 | .md-typeset .gcp-only > .admonition-title, 6 | .md-typeset .gcp-only > summary { 7 | background-color: rgba(255, 128, 0, 0.1); 8 | } 9 | .md-typeset .gcp-only > .admonition-title::before, 10 | .md-typeset .gcp-only > summary::before { 11 | background-color: rgb(255, 128, 0); 12 | -webkit-mask-image: var(--md-admonition-icon--gcp-only); 13 | mask-image: var(--md-admonition-icon--gcp-only); 14 | } 15 | -------------------------------------------------------------------------------- /docs/explanations/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - nais.md 3 | - team.md 4 | - under-the-hood.md 5 | -------------------------------------------------------------------------------- /docs/explanations/nais.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [explanation, nais] 3 | --- 4 | 5 | # What is Nais? 6 | 7 | Nais is a platform aiming to provide you with the technical capabilities you need to develop and run software in a safe and enjoyable way. 8 | 9 | It’s built around the idea that an unobstructed team of people, able and willing to take responsibility for the things they make, perform better than any alternative. 10 | 11 | In order to support this idea, we aim to provide you with functionality that just works™, removing complexities where possible and still providing you with the key insights you need to successfully operate the things you create or provision. 12 | 13 | You can think of the provided functionality as building blocks, where you as a developer can select the ones that fit your specific needs. 14 | 15 | The fundamental building block provided by Nais is a robust and secure runtime environment for your [workloads](../workloads/README.md). 16 | 17 | When your workload is up and running, it’s crucial to be able to observe how it’s doing. Here the platform provides you with the tooling you need to log, emit metrics and run traces. 18 | 19 | Furthermore Nais provides a variety of different ways to persist data, authenticate users and most of the other things you typically need. 20 | 21 | Simply put; our job is to make the operations side of things Nais - allowing you to focus more on building great products. 22 | 23 | ## What does Nais stand for? 24 | 25 | It's original meaning of the abbreviation is: **N**AVs **A**pplication **I**nfrastructure **S**ervices. As you might suspect, we found the abbreviation first. 26 | 27 | We're working on making the 'N' mean 'Norwegian' instead of 'NAVs'. 28 | -------------------------------------------------------------------------------- /docs/explanations/team.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [explanation, nais, team] 3 | --- 4 | 5 | # What is a team? 6 | 7 | Everything in Nais is organized around the concept of a _team_. 8 | 9 | A Nais team should consist of technical personnel involved with developing and operating the team's workloads and resources. 10 | 11 | Being member of a team grants you full access to the team's workloads and provisioned resources. 12 | Limit access to the people that actually need it according to the _principle of least privilege_. 13 | 14 | ## The anatomy of a team 15 | 16 | A team consists of one or more _users_. The team has at least one `owner` and can have multiple `members`. 17 | 18 | An `owner` can add, remove, and change the roles of other users on the team. 19 | 20 | A user can be part of multiple teams. 21 | 22 | ## What happens when you create a team? 23 | 24 | When you [create a team](../operate/how-to/create-team.md), the following will be provisioned for you: 25 | 26 | - An isolated area for your team's workloads and resources in each environment (e.g. `dev` and `prod`) 27 | - A GitHub team with the same name in your GitHub organization. The members of your Nais team will be synchronized with the GitHub team. 28 | - Roles and permissions to access the teams workloads and resources. 29 | 30 | The creator of a team is automatically granted `owner` privileges for the team. 31 | -------------------------------------------------------------------------------- /docs/legal/app-pvk.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Application privacy impact assessments (PVK) 6 | 7 | Before deploying any application that processes and/or stores data to nais, a privacy assessment (PVK) must be conducted. This PVK should be kept reasonably up-to-date through the life cycle of the application. Refer to the [PVK process documentation for details](https://navno.sharepoint.com/sites/intranett-personvern/SitePages/PVK.aspx) \(NAV internal link\). 8 | 9 | Ideally, the language in your PVK should be tech stack agnostic, meaning there will not be any need to change this document as components are changed or the application is [moved between on-premises and cloud clusters](../workloads/explanations/migrating-to-gcp.md). Any technology specific considerations belong in [the risk assessment](app-ros.md). 10 | 11 | For migrating applications to the cloud, a document has been prepared to aid the PVK process internal for NAV [Nais i sky – personvern og sikkerhet. internal for NAV](https://navno.sharepoint.com/:w:/s/Skystrategi817/EcVERNkDfLlIt6s0hjSIxoQBGnyufj1ZEZABLtJ-wIdbNg?e=4%3AOj6D2G&at=9&CID=fc0f7ebb-69d8-4ceb-33f4-2778fa0dfd50) 12 | -------------------------------------------------------------------------------- /docs/legal/app-ros.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Application risk assessments (ROS) 6 | 7 | Before deploying any application to nais, the team owning the application must conduct a risk assessment \(ROS\) in the [TryggNok tool](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566) \(NAV internal link\). This risk assessment should be kept reasonably up-to-date through the lifetime of the application. 8 | 9 | When conducting the risk assessment, any assumptions about underlying component risks can be verified by checking the [Platform risk assessments](nais-ros.md). These may also be referred to in the application risk assessment. 10 | 11 | For details about the ROS process, see the [ROS documentation](https://navno.sharepoint.com/sites/intranett-it/SitePages/IT-sikkerhet-og-risikovurderinger.aspx) \(NAV internal link\). 12 | 13 | -------------------------------------------------------------------------------- /docs/legal/dpa/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Vendor Data Processor Agreements 6 | 7 | Before we can use any \*aaS-service that processes or stores any user data, NAV needs to have a signed Data Processor Agreement \(DPA\) with the vendor in question. These agreements are in place for the vendors supplying components to the nais platform. 8 | 9 | * [Google Cloud Platform DPA](gcp-dpa.md) 10 | * [Microsoft Azure DPA](azure-dpa.md) 11 | * [Aiven DPA](aiven-dpa.md) 12 | 13 | -------------------------------------------------------------------------------- /docs/legal/dpa/aiven-dpa.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Aiven Data Processor Agreement 6 | 7 | NAV has, based on the Schrems II verdict that invalidated The EU-US Privacy Shield transfer mechanism, decided that all cloud services and all storage of data in cloud services shall take place in the EU / EEA. Support is to be given from Aiven supportcenters in EU/EØS. This is already the case regarding Kafka service at Aiven, so the [DPA between NAV and Aiven](https://navno.sharepoint.com/:w:/s/Risikovurderinger668/EdtbCu04JCdEkStS2kV5V_MBb-jDYfwyqa8rnnraSJ7pTg?e=Wj6M6B) is still valid. 8 | 9 | Other relevant documents: 10 | 11 | * [Risk analysis related to the Kafka service and underlying platform](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=190) 12 | 13 | -------------------------------------------------------------------------------- /docs/legal/dpa/azure-dpa.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Azure Data Processor Agreement 6 | 7 | Microsoft has Online Service Terms \(OST\) that govern Customer’s use of the Online Services and the Microsoft Online Services Data Protection Addendum \(DPA\) that sets forth the parties obligations with respect to the processing and security of Customer Data and Personal Data by the Online Services. In addition to the generic OST a set of online services have their own service specific OST. In the event of any conflict or inconsistency between the DPA and any other terms in Customer’s volume licensing agreement \(including the Product Terms or the Online Services Terms\), the DPA shall prevail. 8 | 9 | When moving to Microsoft Azure risk assessment for your application must be updated. [Beslutningsrapport - Avtale med Microsoft](https://navno.sharepoint.com/:w:/s/Risikovurderinger668/EZ_3R0Yw9BtJlJ8phJRjlqwB5TONzEe_E2ypdbH8kXwMEA?e=4AdFVZ) lists the risks related to NAVs use of the services available in Microsoft Azure regarding privacy/GDPR and information security in the overall platform. 10 | 11 | NAV has, based on the Schrems II verdict that invalidated The EU-US Privacy Shield transfer mechanism, decided that all cloud services and all storage of data in cloud services shall take place in the EU / EEA. Apart from this, the DPA with Microsoft is still valid. 12 | 13 | Other relevant documents: 14 | 15 | * [Online Services Data Protection Addendum \(DPA\)](https://www.microsoftvolumelicensing.com/Downloader.aspx?DocumentId=17880) 16 | * [Microsoft Online Service Terms \(OST\)](http://www.microsoftvolumelicensing.com/Downloader.aspx?documenttype=OST&lang=English) 17 | 18 | -------------------------------------------------------------------------------- /docs/legal/dpa/gcp-dpa.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # GCP Data Processor Agreement 6 | 7 | The Data Protection Agreement, DPA, \(named "Data Processing and Security Terms" by Google\) for Google Cloud Platform is part of the Business agreement between NAV and Google Irland Limited. 8 | 9 | [This Business agreement](https://navno.sharepoint.com/:b:/s/Risikovurderinger668/ESrex5wpURVAoHrMfFJTYugBZb2qvJz-evDo6D_FmiF_1w?e=9LzAoo) \(NAV internal link\) is an offline variant which governs our use of the Google Cloud Platform Services. The offline terms uses the online terms as a base, but extend the online terms with for instance English law as the governing law \(not US law\) and 60 days \(not 30\) for NAV to object to changes in the terms. 10 | 11 | When updating the risk assessments for your application, read the [Beslutningsnotat Google avtale](https://navno.sharepoint.com/:w:/s/Skystrategi817/EfB1IyrOMr5Mrt3_3nESZtYBQ-3LHFm_oHH-OkvXx0rkUQ?e=6WsgZE) \(NAV internal link\). This document contains NAVs risks related to GCP and privacy/GDPR, and the risks most highly associated with information security in the Google Cloud platform in general \(in addition the services NAV use in GCP has [their own risk assessments](../nais-ros.md)\). 12 | 13 | NAV has, based on the Schrems II verdict that invalidated The EU-US Privacy Shield transfer mechanism, decided that all cloud services and all storage of data in cloud services shall take place in the EU / EEA. Apart from this, DPA with Google is still valid. Note that any use of Google Support that requires Support staff to access production data will need to be cleared with the NAV CIO in advance. 14 | 15 | The Online data processing terms \(DPA\) can be found [here](https://cloud.google.com/terms/data-processing-terms). 16 | 17 | -------------------------------------------------------------------------------- /docs/legal/nais-pvk.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Platform privacy impact assessments (PVK) 6 | 7 | While nais platform components are used by the teams, the platform in itself is "data agnostic" - that is, the platform team does not know what kind of data is stored and processed on the platform. As such, it is up to each team to [perform a privacy assessment](app-pvk.md) for their data processing and storage needs. 8 | 9 | The exception to the data agnostic rule is data that the platform itself is the processor of - such as configuration data and certain system and access logs (not including application logs, which falls under each individual team's purview). 10 | Thus, the only personally identifiable information (PII) that the platform processes are access logs for developers at NAV. 11 | A PVK for this data processing has been conducted. 12 | 13 | For details on what each team's responsibilites are with respect to data processing on the platform, refer to [roles and responsibilities](roles-responsibilities.md). 14 | 15 | -------------------------------------------------------------------------------- /docs/legal/nais-ros.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Platform risk assessments (ROS) 6 | 7 | The nais team has conducted the following risk assessments: 8 | 9 | * [GCP Lagring av data \(Buckets og Postgres\)](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=219) 10 | * [GCP Tilgangskontrolloppsett](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=218) 11 | * [Tilgang til Kafka fra GCP](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=229) 12 | * [Logger på GCP](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=492) 13 | * [Google Kubernetes Engine](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=481) 14 | * [Sentry i GCP](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=244) 15 | * [Aiven Kafka - Leverandørvurdering](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=190) 16 | * [Aiven ElasticSearch](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=515) 17 | * [Google Secret Manager](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=538) 18 | * [Dataplattform (including BigQuery)](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=607) 19 | * [Bruk av ansatt.nav.no](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=1670) 20 | * [Bruk av Nais Console](https://apps.powerapps.com/play/f8517640-ea01-46e2-9c09-be6b05013566?ID=1921) 21 | 22 | (Note that all risk assessments link to the NAV internal tool TryggNok.) 23 | -------------------------------------------------------------------------------- /docs/legal/roles-responsibilities.md: -------------------------------------------------------------------------------- 1 | --- 2 | conditional: [tenant, nav] 3 | --- 4 | 5 | # Responsibilities - Nais and teams 6 | 7 | "Nais" is a term that denotes a set of services offered by the nais team which the product teams can use when building their products. 8 | The nais services are built on infrastructure and underlying services offered by different infrastructure teams and cloud platform vendors. 9 | In general, responsibilities for services are separated along these lines: 10 | 11 | - Cloud platform vendors are responsible for keeping the infrastructure and underlying platforms running. 12 | - The Nais team is responsible for ensuring the Nais services are up and running and available for use by the product teams. 13 | - The product teams are responsible for their own applications (including business logic, code, data, etc) and for how they use the Nais services. 14 | 15 | As a **general rule** the lines of ownership goes along the project lines. The services running in team-projects are the responsibility of the team. Thus the nais-team owns the usage of cloud services running in the nais-project such as Kubernetes, load-balancing, DNS etc. 16 | 17 | What constitutes a Nais service, an underlying service or what is owned by a product team varies from case to case. 18 | In some instances, the product team is a user of common resources owned by the nais team (e.g. the Grafana stack, or the underlying Kubernetes clusters). 19 | In these cases the nais team operates the resources and is responsible for the service availability. 20 | In other cases the product teams provision their own resources directly from the underlying vendors. 21 | -------------------------------------------------------------------------------- /docs/material_theme_stylesheet_overrides/uu.css: -------------------------------------------------------------------------------- 1 | .md-header-nav__source a { 2 | text-decoration: none; 3 | } 4 | 5 | [data-md-color-primary="blue-grey"] a { 6 | --md-typeset-a-color: #6c9fff; /* This is a small tweak to bump the contrast on links up to 4.6 */ 7 | } 8 | 9 | .md-footer-copyright { 10 | color: #ffffff; 11 | } 12 | 13 | .md-content a { 14 | text-decoration: underline; 15 | } 16 | 17 | @media screen and (min-width: 60em) { 18 | .md-search__inner { 19 | width: 14.7rem; 20 | } 21 | } 22 | 23 | .md-search__input { 24 | background-color: hsla(0, 0%, 96%, 1); 25 | color: hsla(0, 0%, 0%, 0.87); 26 | } 27 | 28 | .md-search__icon svg { 29 | color: hsla(0, 0%, 0%, 0.87); 30 | } 31 | 32 | .md-search__input:hover { 33 | background-color: hsla(0, 0%, 100%, 1); 34 | } 35 | 36 | .md-search__input::placeholder { 37 | color: hsla(0, 0%, 0%, 0.87); 38 | } 39 | 40 | [data-md-toggle="search"]:checked ~ .md-header .md-search__input { 41 | color: hsla(0, 0%, 0%, 0.87); 42 | background-color: hsla(0, 0%, 100%, 1); 43 | } 44 | 45 | ::backdrop { 46 | background-color: rgba(0, 0, 0, 0.6); 47 | } 48 | -------------------------------------------------------------------------------- /docs/observability/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/observability/alerting/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/observability/logging/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/observability/logging/how-to/audit-logs.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, logging] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Audit logs 7 | 8 | Most applications where a user processes data related to another user need to log audit statements, detailing which user did what action on which subject. These logs need to follow a specific format and be accessible by ArcSight. 9 | 10 | See [naudit](https://github.com/navikt/naudit) for how to set up the logging, and details on the log format. 11 | -------------------------------------------------------------------------------- /docs/observability/logging/how-to/disable.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Disable log storage for a specific application 3 | tags: [how-to, logging, observability] 4 | --- 5 | 6 | # Disable persistent application logs 7 | 8 | This guide will help you disable persistent log storage for an application. This is useful if you have an application whose logs are not useful or are causing too much noise in the logs. 9 | 10 | !!! warning 11 | Disabling logging will not affect the application's ability to log to stdout/stderr that can still be found in nais console or using the `kubectl logs` command. It will only disable the persistent storage of logs. 12 | 13 | Simply set the `spec.observability.logging.destinations` in your application manifest to an empty list to disable logging. 14 | 15 | ???+ note ".nais/application.yaml" 16 | ```yaml hl_lines="6" 17 | … 18 | spec: 19 | observability: 20 | logging: 21 | destinations: [] 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/observability/logging/how-to/kibana.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: This guide will help you get started with Kibana. 3 | tags: [how-to, logging, kibana] 4 | conditional: [tenant, nav] 5 | --- 6 | # Get started with Elastic Kibana 7 | 8 | !!! warning "Not supported by Nais" 9 | 10 | This logging solution is not supported by Nais. See [Loki](./loki.md) for the new default logging solution. 11 | 12 | This guide will help you get stared sending application logs to Elastic Kibana and writing queries to search for logs. 13 | 14 | ## Enable logging to Elastic Kibana 15 | 16 | Elastic Kibana can be enabled by setting the list of logging destinations in your nais application manifest. 17 | 18 | ???+ note ".nais/application.yaml" 19 | ```yaml hl_lines="6" 20 | … 21 | spec: 22 | observability: 23 | logging: 24 | destinations: 25 | - id: elastic 26 | ``` 27 | 28 | ## Get access to Kibana 29 | 30 | In order to get access to logs.adeo.no you need to have the correct access rights added to your AD account. This can be requested through your Personnel Manager. 31 | 32 | These permissions will give you access: 33 | 34 | ```text 35 | 0000-GA-Logganalyse 36 | 0000-GA-Logganalyse_FullVerdikjede_Prod 37 | 0000-GA-Logganalyse_FullVerdikjede_UTQ 38 | ``` 39 | 40 | ## Working with Kibana 41 | 42 | When you open Kibana you are prompted to select a workspace, select "Nav Logs" to start viewing your application logs. 43 | 44 | Once the page loads you will see an empty page with a search bar. This is the query bar, and it is used to search for logs. You can use the query bar to search for logs by message, by field, or by a combination of both. 45 | 46 | The query language is called [Kibana Query Language](../reference/kql.md) (`KQL`). KQL is a simplified version of Lucene query syntax. You can use KQL to search for logs by message, by field, or by a combination of both. 47 | 48 | There is also a time picker in the upper right corner of the page. You can use the time picker to select a time range to search for logs. The default time range is the last 15 minutes. If no logs shows up, try to increase the time range. 49 | -------------------------------------------------------------------------------- /docs/observability/logging/how-to/kubectl.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: View logs from the command line using kubectl. 3 | tags: [how-to, logging, observability, command-line] 4 | --- 5 | 6 | # View logs from the command line 7 | 8 | This guide will show you how to view logs from the command line using `kubectl`. 9 | 10 | ## Prerequisites 11 | 12 | - You have installed the [kubectl](../../../operate/how-to/command-line-access.md) command-line tool. 13 | - You have access to the [team](../../../explanations/team.md) where the application is running. 14 | 15 | ## Find the pod name 16 | 17 | You can view logs for a specific pod. First, you need to find the name of the pod you want to view logs for. 18 | 19 | List all pods in the namespace: 20 | 21 | ```bash 22 | kubectl get pods -n 23 | ``` 24 | 25 | ## View logs 26 | 27 | View logs for a specific pod: 28 | 29 | ```bash 30 | kubectl logs -n 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/observability/logging/how-to/logs-in-dashboards.md: -------------------------------------------------------------------------------- 1 | # Adding logs to your Grafana dashboard 2 | 3 | In this guide, you will learn how to add logs to your Grafana dashboards. Logs are a valuable source of information for debugging and monitoring your applications. By adding logs to your Grafana dashboards, you can correlate logs with metrics and traces to get a complete picture of your application's health. 4 | 5 | ## Prerequisites 6 | 7 | - [Enabled Loki logging for your application](./loki.md#enable-logging-to-grafana-loki) 8 | - A Grafana dashboard 9 | 10 | ## Add logs to your dashboard 11 | 12 | To add logs to your Grafana dashboard, you need to open the dashboard in edit mode and add a new Visualization to the dashboard. This will open the Visualization editor where you can configure the log query and display options. 13 | 14 | ![Add Visualization](../../../assets/grafana-add-logs-panel.png) 15 | 16 | 1. Open your Grafana dashboard in edit mode. 17 | 1. Click the `Add` button in the top menu and select `Visualization`. 18 | 1. Select `Logs` as the panel visualization type (`A`) 19 | 1. Optionally, you can configure log display and de-duplication (`B`). 20 | 1. Select the Loki data source (`C`). 21 | 1. Enter your LogQL query in the query editor (`D`). Here you can filter logs by indexed labels such as `service_name`, and `service_namespace`. 22 | 1. Add additional query operations such as Json parsing, filtering, and aggregation (`E`). 23 | 24 | In the above example, we are querying logs from the `service_name` label with the value `my-app`. We then parse the JSON log message (ignoring any parsing errors) and filter logs with the `level` field set to `error`. Lastly we format the log line as level and message (`{{ .level }} {{ .msg }}`). 25 | -------------------------------------------------------------------------------- /docs/observability/logging/reference/destinations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Log Destinations 3 | description: Available log destinations for application logging in Nais. 4 | tags: [reference, logging] 5 | --- 6 | 7 | # Log Destinations 8 | 9 | Log destinations are the different places where logs can be sent to. All environments have a default log destination, please see the [environments overview](../../../workloads/reference/environments.md), but you can configure your application to send logs to other destinations as well. 10 | 11 | ## Configuration 12 | 13 | To configure a log destination for your application, add the following configuration to your `Application` resource: 14 | 15 | ```yaml 16 | apiVersion: nais.io/v1alpha1 17 | kind: Application 18 | metadata: 19 | name: my-application 20 | spec: 21 | observability: 22 | logging: 23 | destinations: 24 | - id: loki 25 | ``` 26 | 27 | ## Destinations 28 | 29 | The following log destinations are available in Nais: 30 | 31 | {% if tenant() != "ssb" %} 32 | - [`loki`](../how-to/loki.md#enable-logging-to-loki) 33 | {% endif %} 34 | - [`team_logs`](../how-to/team-logs.md#enable-team-logs) 35 | {% if tenant() == "nav" %} 36 | - [`elastic`](../how-to/kibana.md#enable-logging-to-elastic-kibana) (deprecated) 37 | {% endif %} 38 | 39 | It is possible to specify multiple destinations. 40 | -------------------------------------------------------------------------------- /docs/observability/logging/reference/loki-labels.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Loki label reference documentation for querying logs in Grafana Loki. 3 | tags: [reference, loki, logging] 4 | --- 5 | 6 | # Loki Labels Reference 7 | 8 | In Grafana Loki, logs are stored as key-value pairs called labels. Labels are used to filter, aggregate, and search for logs and can be used in LogQL queries to search for logs by message, by field, or by a combination of both. 9 | 10 | The following labels are available in Grafana Loki by default: 11 | 12 | | Field | Description | Applicable to | 13 | | -------------------- | ------------------------------------------------------------------------- | ------------- | 14 | | `detected_level` | The log level detected by the log parser. | All | 15 | | `service_name` | The name of the application that generated the log line. | All | 16 | | `service_namespace` | The namespace of the application that generated the log line. | All | 17 | | `k8s_container_name` | The name of the Kubernetes container that generated the log line. | Kubernetes | 18 | | `k8s_pod_name` | The name of the Kubernetes pod that generated the log line. | Kubernetes | 19 | | `k8s_node_name` | The name of the Kubernetes node that generated the log line. | Kubernetes | 20 | | `k8s_cluster_name` | The name of the Kubernetes cluster that generated the log line. | Kubernetes | 21 | | `collector_name` | The name of the log collector that ingested the log line. | All | 22 | | `kind` | The kind of log line. Can be `exception`, `event` `log` or `measurement`, | Faro SDK | 23 | -------------------------------------------------------------------------------- /docs/observability/metrics/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/observability/metrics/how-to/expose.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Expose metrics from your application 3 | tags: [how-to, metrics, prometheus, observability] 4 | --- 5 | # Expose metrics from your application 6 | 7 | This guide will show you how to expose metrics from your application, and how to configure Prometheus to scrape them. 8 | 9 | See further [explanations on metrics](../README.md) for more details 10 | 11 | ## 1. Add metric to your application 12 | 13 | Most languages have a Prometheus client library available. See [Prometheus client libraries](https://prometheus.io/docs/instrumenting/clientlibs/) for a list of available libraries. These libraries provides examples as to how to instrument your application using the correct metric types. 14 | 15 | Once instrumented, your application must serve these metrics using HTTP on a given `path` (e.g. `/metrics`). 16 | 17 | ## 2. Enable metrics in [manifest](../../../workloads/application/reference/application-spec.md) 18 | 19 | ```yaml 20 | spec: 21 | prometheus: 22 | enabled: true 23 | path: /metrics 24 | ``` 25 | 26 | Once this manifest is deployed, Prometheus will start scraping your application for metrics on the provided `path`. 27 | 28 | -------------------------------------------------------------------------------- /docs/observability/metrics/how-to/grafana-from-infoscreen.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: How to show Grafana on an infoscreen 3 | tags: [how-to, metrics, grafana] 4 | conditional: [tenant, nav] 5 | --- 6 | # Show Grafana on infoscreen 7 | 8 | To access Grafana from an infoscreen, some additional steps are required. 9 | 10 | ## Create service account token 11 | 12 | 1. Find your team's service account in [Grafana](https://grafana.<>.cloud.nais.io/org/serviceaccounts). 13 | 1. Click on `Add token`, and set the desired expiration. 14 | 1. Copy the token value, and use in the following step. 15 | 16 | ## Access Grafana from infoscreen browser 17 | 18 | To add the service account credentials to the header of your requests, you can use the [Modify Header Value](https://mybrowseraddon.com/modify-header-value.html) browser extension available for Chrome and Firefox. 19 | 20 | Set the following configuration in the extension: 21 | 22 | | Field | Value | 23 | | ------------ | --------------------------------------------------------- | 24 | | URL | `https://grafana-infoskjerm.<>.cloud.nais.io/*` | 25 | | Domain | ✅ | 26 | | Header name | `Authorization` | 27 | | Add | ✅ | 28 | | Header value | `Bearer ` | 29 | | State | Active | 30 | 31 | -------------------------------------------------------------------------------- /docs/observability/metrics/reference/grafana.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [reference, grafana, metrics] 3 | --- 4 | 5 | # Grafana Glossary 6 | 7 | This glossary contains terms and concepts related to Grafana. 8 | 9 | ## Dashboard 10 | 11 | A dashboard is a collection of panels arranged in a grid layout. Each panel is a single visualization or a single query result. You can add multiple panels to a dashboard to create a complete view of your application. 12 | 13 | * [Guide: Create a dashboard in Grafana](../how-to/dashboard.md) 14 | * [Grafana docs: Dashboards](https://grafana.com/docs/grafana/latest/dashboards/) 15 | 16 | ## Panel 17 | 18 | A panel is a single visualization or a single query result. You can add multiple panels to a dashboard to create a complete view of your application. 19 | 20 | 21 | ## Data source 22 | 23 | A data source is a source of data that you can query in Grafana. Grafana supports a variety of data sources, including Prometheus (metrics), Tempo (traces), and Loki (logs). 24 | 25 | * [Grafana docs: Data sources](https://grafana.com/docs/grafana/latest/datasources/) 26 | 27 | ## Query 28 | 29 | A query is a request for data from a data source. In Grafana, you can write queries to visualize your metrics, logs, and traces. 30 | 31 | ## Visualization 32 | 33 | A visualization is a graphical representation of your data. Grafana supports a variety of visualizations, including graphs, tables, and heatmaps. 34 | 35 | * [Grafana docs: Panels and visualizations](https://grafana.com/docs/grafana/latest/panels-visualizations/) 36 | 37 | ## Alerting 38 | 39 | Grafana has a built-in alerting system that allows you to set up alerts for your metrics. You can create alert rules that are evaluated at regular intervals, and when the alert rule conditions are met, Grafana will send notifications to the configured notification channels. 40 | 41 | * [Guide: Alerting in Grafana](../../alerting/how-to/grafana.md) 42 | -------------------------------------------------------------------------------- /docs/observability/metrics/reference/metrics.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [reference, metrics, prometheus] 3 | --- 4 | 5 | # Metrics reference 6 | 7 | ## Retention 8 | 9 | When using Prometheus the retention is 30 days. 10 | If you need data stored longer than what Prometheus support, we recommend using [BigQuery](../../../persistence/bigquery/README.md). 11 | Then you have full control of the database and retention. 12 | 13 | ## Accessing prometheus 14 | 15 | You can visit the prometheus instance for your environment by visiting the following URL: 16 | 17 | ```plaintext 18 | https://prometheus..<>.cloud.nais.io 19 | ``` 20 | 21 | Replace `` with the environment you want to access, e.g. `dev`, `prod` etc. 22 | -------------------------------------------------------------------------------- /docs/observability/metrics/reference/promql.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: PromQL reference documentation for querying metrics in Prometheus. 3 | tags: [reference, prometheus, metrics] 4 | --- 5 | 6 | # PromQL Reference 7 | 8 | PromQL is a query language for Prometheus monitoring system. It allows you to select and aggregate time series data in real time. PromQL is used to [create dashboards in Grafana][howto-grafana-dashboard], and to [create alerts with Alertmanager][howto-alertmanager-alerts]. 9 | 10 | [howto-grafana-dashboard]: ../how-to/dashboard.md 11 | [howto-alertmanager-alerts]: ../../alerting/how-to/prometheus-basic.md 12 | 13 | ## Basic Syntax 14 | 15 | A basic PromQL query can be as simple as a metric name: `http_requests_total`. This will return the current value of the `http_requests_total` metric. 16 | 17 | ## Data Types 18 | 19 | PromQL supports a variety of data types: 20 | 21 | - Scalars: `1`, `3.14`, `0.5` 22 | - Strings: `"hello"`, `"world"` 23 | - Vectors: `http_requests_total{job="api-server"}` 24 | - Range Vectors: `http_requests_total{job="api-server"}[5m]` 25 | 26 | ## Operators 27 | 28 | PromQL supports a variety of operators: 29 | 30 | - Arithmetic: `+`, `-`, `*`, `/`, `%`, `^` 31 | - Comparison: `==`, `!=`, `>`, `<`, `>=`, `<=` 32 | - Logical: `and`, `or`, `unless` 33 | 34 | ## Functions 35 | 36 | PromQL includes a variety of functions, such as: 37 | 38 | - `rate(v range-vector)`: calculates the per-second average rate of time series in a range vector 39 | - `sum(v vector)`: calculates the sum of all values in the vector 40 | - `avg(v vector)`: calculates the average of all values in the vector 41 | 42 | ## Aggregation 43 | 44 | PromQL allows you to aggregate time series: `sum(http_requests_total) by (status)`. This will return the sum of `http_requests_total` for each `status` label value. 45 | 46 | ## More Information 47 | 48 | For more detailed information, refer to the [official PromQL documentation][prometheus-querying-basics] and the [example Prometheus queries][prometheus-example-queries]. 49 | 50 | [prometheus-querying-basics]: https://prometheus.io/docs/prometheus/latest/querying/basics/ 51 | [prometheus-example-queries]: https://prometheus.io/docs/prometheus/latest/querying/examples/ 52 | -------------------------------------------------------------------------------- /docs/observability/tracing/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/observability/tracing/how-to/context-propagation.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Learn how to propagate trace context across process boundaries in a few common scenarios. 3 | tags: [how-to, tracing, observability] 4 | --- 5 | 6 | # Trace context propagation 7 | 8 | Each Span carries a Context that includes metadata about the trace (like a unique trace identifier and span identifier) and any other data you choose to include. This context is propagated across process boundaries, allowing all the work that's part of a single trace to be linked together, even if it spans multiple services. 9 | 10 | This guide explains how to propagate trace context across process boundaries in a few common scenarios. If you are using [auto-instrumentation](../../how-to/auto-instrumentation.md), trace context propagation is already handled for you. 11 | 12 | [:octicons-link-external-24: OpenTelemetry Context Propagation on opentelemetry.io](https://opentelemetry.io/docs/concepts/context-propagation/) 13 | 14 | ## Propagate trace context in HTTP requests 15 | 16 | When a service makes an HTTP request to another service, it should include the trace context in the request headers. The receiving service can then use this context to create a new Span that's part of the same trace. OpenTelemetry provides a standard for how trace context should be propagated in HTTP requests, called the [W3C Trace Context](https://www.w3.org/TR/trace-context/) standard. 17 | 18 | * [OpenTelemetry Setup in Spring Boot Application](https://opentelemetry.io/docs/languages/java/automatic/spring-boot) 19 | * [OpenTelemetry Setup in Ktor Application](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/ktor/ktor-2.0/library) 20 | -------------------------------------------------------------------------------- /docs/observability/tracing/how-to/elastic-apm.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: This guide will help you get started with sending tracing data to Elastic APM. 3 | tags: [how-to, opentelemetry, kibana] 4 | conditional: [tenant, nav] 5 | --- 6 | # Tracing data in Elastic APM 7 | 8 | !!! warning "Deprecation notice" 9 | 10 | Support for Elastic APM in Nais has been deprecated and will be removed at the end of the year. 11 | 12 | For nais applications running on-prem (dev-fss and prod-fss) you have the option to send telemetry data to Elastic APM in adition to Grafana. This guide will help you get started with Elastic APM for your application. 13 | 14 | ## Enable auto-instrumentation for Elastic APM 15 | 16 | Elastic APM can be enabled by setting the list of auto-instrumentation destinations in your nais application manifest. 17 | 18 | ```yaml hl_lines="7-8" 19 | spec: 20 | observability: 21 | autoInstrumentation: 22 | enabled: true 23 | runtime: "java" 24 | destinations: 25 | - id: "elastic-apm" 26 | ``` 27 | 28 | It is possible to send data to multiple destinations (such as `grafana-lgtm`) by adding more destinations to the list. 29 | 30 | ### Service Environment 31 | 32 | If you have multiple virutal environments for your application such ac `q1`, `t2`, or `p`, you can specify the environment in the `OTEL_RESOURCE_ATTRIBUTES` environment variable. 33 | 34 | ```yaml 35 | spec: 36 | env: 37 | - name: OTEL_RESOURCE_ATTRIBUTES 38 | value: "deployment.environment.name=q1" 39 | ``` 40 | 41 | ## Accessing the Elastic APM UI 42 | 43 | The Elastic APM UI is available at [logs.adeo.no](https://logs.adeo.no/app/apm/services) and requires you to log in with your NAV account and by selecting the `APM` menu item. 44 | 45 | From there you can select the application (or service as they are called in Elastic APM) you want to inspect. 46 | -------------------------------------------------------------------------------- /docs/observability/tracing/reference/trace-semconv.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [reference, otel, observability, tracing] 3 | --- 4 | 5 | # OpenTelemetry Trace Semantic Conventions 6 | 7 | OpenTelemetry Trace Semantic Conventions can be found at [opentelemetry.io](https://opentelemetry.io/docs/specs/semconv/general/trace/). 8 | -------------------------------------------------------------------------------- /docs/operate/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - Console: console.md 5 | - CLI: cli 6 | - naisdevice: naisdevice 7 | - ... 8 | -------------------------------------------------------------------------------- /docs/operate/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [explanation, operate] 3 | --- 4 | 5 | # Manage your workloads and services 6 | 7 | This section covers how to manage your workloads and services on the Nais platform. 8 | It describes the different options available, and how to use them. 9 | 10 | Most of the management tasks can be done through the [Nais Console](console.md), which is a web-based interface. 11 | 12 | Some more advanced use-cases still requires you to interact with the platform using the Kubernetes CLI, `kubectl`. 13 | 14 | ## Related pages 15 | 16 | :bulb: [Learn more about Nais Console](console.md) 17 | 18 | :dart: [Setup command line access](how-to/command-line-access.md) 19 | -------------------------------------------------------------------------------- /docs/operate/cli/.pages: -------------------------------------------------------------------------------- 1 | title: nais-cli 2 | nav: 3 | - ... 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | -------------------------------------------------------------------------------- /docs/operate/cli/README.md: -------------------------------------------------------------------------------- 1 | # nais-cli 2 | 3 | nais-cli is a CLI application that provides some useful commands and utilities for interacting with the Nais platform. 4 | 5 | ## Prerequisites 6 | 7 | - [naisdevice](../naisdevice/README.md) 8 | 9 | ## Installation 10 | 11 | - [Install nais-cli](how-to/install.md) 12 | 13 | ## Usage 14 | 15 | See available subcommands under the Reference section in the navigation sidebar. 16 | 17 | !!! warning "Flag ordering" 18 | 19 | nais-cli requires all flags to appear **before** arguments. Otherwise, the flags will be interpreted as arguments. 20 | 21 | :white_check_mark: OK: 22 | ```shell 23 | nais start --topics events appname teamname 24 | ``` 25 | 26 | :x: Not OK: 27 | 28 | ```shell 29 | nais start appname teamname --topics events 30 | ``` 31 | 32 | ## Telemetry 33 | 34 | We collect simple telemetry about usage and error messages to get a view of which features are used, and what kind of problems our users have with using the tool. 35 | If you don't want to share your usage you can opt out following the [Console Do Not Track (DNT)](https://consoledonottrack.com/) standard. 36 | 37 | Copy this into your terminal, or even better add it to your shell-config (for example `.zshrc` or `.bashrc`): 38 | 39 | ``` shell 40 | export DO_NOT_TRACK=1 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/operate/cli/how-to/install.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [command-line, how-to] 3 | --- 4 | 5 | # Install nais-cli 6 | 7 | === "macOS" 8 | 9 | 1. Install [Homebrew](https://brew.sh/) (unless you already have it) 10 | 2. Add the nais tap 11 | ```bash 12 | brew tap nais/tap 13 | ``` 14 | 3. Install the nais-cli 15 | ```bash 16 | brew install nais 17 | ``` 18 | 19 | === "Ubuntu" 20 | 21 | !!! tip 22 | The PPA repo is shared between nais-cli and [naisdevice](../../naisdevice/README.md), so the first step may be unnecessary. 23 | 24 | 1. Add the nais PPA repo: 25 | ``` 26 | NAIS_GPG_KEY="/etc/apt/keyrings/nav_nais_gar.asc" 27 | curl -sfSL "https://europe-north1-apt.pkg.dev/doc/repo-signing-key.gpg" | sudo dd of="$NAIS_GPG_KEY" 28 | echo "deb [arch=amd64 signed-by=$NAIS_GPG_KEY] https://europe-north1-apt.pkg.dev/projects/nais-io nais-ppa main" | sudo tee /etc/apt/sources.list.d/nav_nais_gar.list 29 | sudo apt update 30 | ``` 31 | 2. Install the nais package: 32 | ``` 33 | sudo apt install nais 34 | ``` 35 | 36 | === "Windows" 37 | 38 | ### Install using Scoop 39 | 40 | 1. Install [Scoop](https://scoop.sh) unless you already have it. 41 | 2. Add the nais bucket 42 | ```powershell 43 | scoop bucket add nais https://github.com/nais/scoop-bucket 44 | ``` 45 | 3. Install nais-cli 46 | ```powershell 47 | scoop install nais-cli 48 | ``` 49 | 50 | === "Manual" 51 | 52 | Download the archive for windows from [nais/cli](https://github.com/nais/cli/releases/latest) and unpack the tool to a directory on your `$PATH`. 53 | If you are unable to run nais after installing, check out our [troubleshooting guide](troubleshooting.md). 54 | 55 | -------------------------------------------------------------------------------- /docs/operate/cli/how-to/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [command-line, how-to] 3 | --- 4 | 5 | # Troubleshooting nais-cli 6 | 7 | ## `Could not create process with command` 8 | 9 | If you get an error message like this (the path may vary): 10 | ``` 11 | > nais 12 | Could not create process with command '"C:\Users\\scoop\apps\nais-cli\current\nais.exe" '. 13 | ``` 14 | which is the shim hiding the actual error message: 15 | ``` 16 | > C:\Users\\scoop\apps\nais-cli\current\nais.exe 17 | ResourceUnavailable: Program 'nais.exe' failed to run: An error occurred trying to start process 'C:\Users\\scoop\apps\nais-cli\current\nais.exe' with working directory ''. Access is denied.At line:1 char:1 18 | + C:\Users\\scoop\apps\nais-cli\current\nais.exe 19 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~. 20 | ``` 21 | then you need to exclude the folder `%USERPROFILE%\scoop\apps\nais-cli` from Windows Security: 22 | 23 | 1. Open Windows Security. 24 | 2. Select Virus & threat protection. 25 | 3. Select Manage settings, and then under Exclusions, select Add or remove exclusions. 26 | 4. Select Add an exclusion, and then select folder. 27 | 5. Add the folder `%USERPROFILE%\scoop\apps\nais-cli`. 28 | 29 | Alternatively, from an elevated PowerShell: 30 | ``` 31 | > Add-MpPreference -ExclusionPath %USERPROFILE%\scoop\apps\nais-cli 32 | ``` 33 | 34 | ## Mac: User xxx does not exists 35 | If you get an error message like this when running `brew install nais` 36 | 37 | clear the envvariable USER 38 | ``` 39 | export USER= 40 | ``` 41 | verify that USER is empty; 42 | ``` 43 | echo $USER 44 | ``` 45 | run `brew install nais` again -------------------------------------------------------------------------------- /docs/operate/cli/reference/kubeconfig.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [command-line, reference] 3 | --- 4 | 5 | # kubeconfig command 6 | 7 | Create a kubeconfig file for connecting to available clusters for you. 8 | This requires that you have the gcloud command line tool installed, configured and logged in. 9 | You can log in with `gcloud auth login --update-adc`. 10 | 11 | ```bash 12 | nais kubeconfig 13 | ``` 14 | 15 | | Flag | Short | Description | 16 | | --------- | ----- | ----------------------------------------------------------------------- | 17 | | overwrite | -o | Overwrite config already in the kubeconfig-file | 18 | | clear | -c | Delete config before retrieving new one | 19 | | exclude | -e | Exclude clusters from the config, comma separated list of cluster names | 20 | | verbose | -v | More output, mostly useful combined with overwrite | 21 | 22 | !!! info "hello" 23 | You don't have to use the environment variable `KUBECONFIG`, instead you can use the default kubectl-folder `~/.kube`. 24 | Delete the old `navikt/kubeconfig`-repo and remove the environment file, and then run `nais kubeconfig`. 25 | -------------------------------------------------------------------------------- /docs/operate/console.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [console, explanation, operate] 3 | --- 4 | 5 | # Console 6 | 7 | Nais Console is a web-based interface for managing your workloads and services on the Nais platform. It aims to provide a user-friendly way to interact with the platform, without needing to use the command line. 8 | 9 | It tries to provide you with insight into what you've got running on the platform. Is everything running as expected? Are you utilizing the resources you allocate effectively? 10 | 11 | The Console is designed to be self-service, meaning that you can manage your workloads and services without needing to involve the Nais team. This includes creating, updating, and deleting workloads, as well as managing secrets and other resources. 12 | 13 | Access Nais Console at [console.<>.cloud.nais.io](https://console.<>.cloud.nais.io). 14 | -------------------------------------------------------------------------------- /docs/operate/how-to/command-line-access.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [command-line, how-to, operate] 3 | --- 4 | 5 | # Setup command line access 6 | 7 | This guide shows you how to set up command line tools for accessing Nais clusters 8 | 9 | ## Prerequisites 10 | 11 | - [naisdevice](../naisdevice/how-to/install.md) installed 12 | - [nais-cli](../cli/how-to/install.md) installed 13 | 14 | ## Install gcloud 15 | 16 | Follow Googles instructions on how to install [gcloud](https://cloud.google.com/sdk/docs/install) for your OS 17 | 18 | ## Authenticate using gcloud 19 | 20 | ```shell 21 | gcloud auth login --update-adc 22 | ``` 23 | 24 | This will open your browser. 25 | Follow the instructions to authenticate using the email from your organization. 26 | 27 | When successfully authenticated, you will be shown "You are now authenitcated with the gcloud CLI!" in your browser. 28 | You can now close the browser window. 29 | 30 | You will also need to install a plugin in order to authenticate to the Kubernetes clusters: 31 | 32 | ```shell 33 | gcloud components install gke-gcloud-auth-plugin 34 | ``` 35 | 36 | {%- if tenant() == "nav" %} 37 | ## Install kubelogin for access to on-prem clusters 38 | 39 | Follow Microsoft's instructions on how to install [kubelogin](https://azure.github.io/kubelogin/install.html) for your OS. 40 | {%- endif %} 41 | 42 | ## Generate kubeconfig file 43 | 44 | Use nais-cli to generate the kubeconfig file that grants access to the Nais clusters. 45 | 46 | ```shell 47 | nais kubeconfig 48 | ``` 49 | 50 | A successful run will output how many clusters and where the kubeconfig file is written to. 51 | 52 | ## Install kubectl 53 | 54 | Follow the instruction to install [kubectl](https://kubernetes.io/docs/tasks/tools/) for your OS. 55 | The next step of this guide verify that you have access to our clusters, so you can skip the "Verify kubectl configuration" section in the instructions. 56 | 57 | ## Verify access 58 | 59 | ```shell 60 | kubectl --context '' get ns 61 | ``` 62 | 63 | If you are unsure about which environments are available, you can list them with: 64 | 65 | ```shell 66 | kubectl config get-clusters 67 | ``` 68 | -------------------------------------------------------------------------------- /docs/operate/how-to/create-team.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [team, how-to, operate] 3 | --- 4 | 5 | # Create a Nais team 6 | 7 | This how-to guide shows you how to create a Nais team. 8 | 9 | ## Prerequisites 10 | 11 | - [naisdevice installed](../naisdevice/how-to/install.md), to be able to access Console. 12 | 13 | ## Create your team 14 | 15 | 1. Open [Nais Console](https://console.<>.cloud.nais.io/) in your browser, and authenticate. 16 | 2. Click on "Create" 17 | 3. Choose a team name, add a description of the team and the Slack channel that is mentioned in the prerequisites. 18 | 4. Click "Create" 19 | 20 | Your team will now be created, and you will be the owner. 21 | 22 | Read more about what resources are created for your team [here](../../explanations/team.md). 23 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - ... 4 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [naisdevice, explanation, operate] 3 | --- 4 | 5 | # naisdevice 6 | 7 | naisdevice is a mechanism that lets you connect to services not available on the public internet from your machine. 8 | 9 | Examples of such services are: 10 | 11 | - Access to the Nais cluster with [kubectl](../how-to/command-line-access.md) 12 | - Applications on [internal domains](../../workloads/reference/environments.md) 13 | - Internal Nais services such as [Nais Console](../console.md). 14 | 15 | {% if tenant() == "nav" %} 16 | 17 | Before connecting, your machine needs to meet certain requirements. These requirements are enforced by a third-party service called [Kolide](https://kolide.com/) that is installed alongside naisdevice. 18 | 19 | Kolide will notify you through Slack when something is wrong with your machine, and will guide you through the process of fixing it. 20 | {% endif %} 21 | 22 | :dart: [**Get started with naisdevice**](how-to/install.md) 23 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/explanations/.pages: -------------------------------------------------------------------------------- 1 | title: 💡 Explanations 2 | conditional: [tenant, nav] 3 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/explanations/jita.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [naisdevice, jita, explanation] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Just In Time Access (JITA) 7 | 8 | ## Providing access to sensitive information 9 | 10 | When you start naisdevice you will not be automatically connected to all the available gateways. In order to reach some of the services you will need to request "just in time access". The purpose of this mechanism is to provide temporary access to selected production environments through self service while keeping an audit trail. JITA requires authentication through the Microsoft login portal. 11 | 12 | !!! info 13 | The gateways currently requiring JITA are `aiven-prod`, `onprem-k8s-prod` and `postgres-prod`. 14 | 15 | Access can be requested via the naisdevice menu or through the [nais cli](../../cli/reference/device.md#jita). 16 | 17 | Once authenticated you will be presented with a form where you have to supply a short reason for why access is needed and for how long. You will then be granted access for the requested amount of time instantly and automatically. 18 | 19 | ![A screenshot that shows the part of the form, where you supply the short reason for why access is needed and for how long. The label of the input field is "Reason". A slider below allows you to select the duraction.](../../../assets/jita_portal.png) 20 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/how-to/.pages: -------------------------------------------------------------------------------- 1 | title: 🎯 How-To 2 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/how-to/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [naisdevice, how-to] 3 | --- 4 | 5 | # Troubleshooting naisdevice 6 | 7 | {%- if tenant() == "nav" %} 8 | ## Kolide 9 | 10 | > naisdevice cannot connect, yet `/msg @Kolide status` reports that everything is fine 11 | 12 | - Disconnect and re-connect `naisdevice` 13 | 14 | > Kolide is reporting that your device has not been seen "in a long time" 15 | 16 | - Reinstall ([uninstall](uninstall.md) -> [install](install.md)) 17 | {%- endif %} 18 | 19 | ## Browser not opening 20 | 21 | > Browser does not open after you click connect. 22 | 23 | Restart your default browser. 24 | 25 | ## Firewall blocks outgoing UDP connections 26 | 27 | - Outgoing UDP connections to 51820/UDP must be open in your firewall and or modem provided by your ISP. 28 | - Try using hotspot to eliminate router config problems (remember to disconnect from WiFi on your hotspot device and make sure you use 4G/5G by checking https://www.ipaddress.my/) 29 | 30 | ## Fresh start 31 | 32 | - Stop naisdevice 33 | - Remove configuration directory 34 | - Mac: `rm -r "~/Library/Application Support/naisdevice/"` 35 | - Linux: `rm -r "~/.config/naisdevice/"` 36 | - Windows: `rmdir /s "C:\ProgramData\NAV\naisdevice\"` 37 | - Start naisdevice 38 | 39 | ## Windows virus scanner 40 | 41 | > Windows virus scanner blocks naisdevice.exe installer 42 | 43 | - Make sure you downloaded from the right source, the signature is valid and the checksum matches the file! 44 | {%- if tenant() == "nav" %} 45 | - See 46 | {%- endif %} 47 | - Try adding an exception: Windows Security / Virus & threat protection / Exclusions. 48 | - Someone reported that running naisdevice.exe from cmd.exe can help. 49 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/how-to/uninstall-kolide.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [naisdevice, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Uninstall Kolide 7 | 8 | === "macOS" 9 | 1. Stop and remove Kolide and the related launch mechanisms 10 | ```bash 11 | sudo /bin/launchctl unload /Library/LaunchDaemons/com.kolide-k2.launcher.plist 12 | sudo /bin/rm -f /Library/LaunchDaemons/com.kolide-k2.launcher.plist 13 | ``` 14 | 2. Delete files, configuration and binaries 15 | ```bash 16 | sudo /bin/rm -rf /usr/local/kolide-k2 17 | sudo /bin/rm -rf /etc/kolide-k2 18 | sudo /bin/rm -rf /var/kolide-k2 19 | ``` 20 | 21 | === "Windows" 22 | 1. Uninstall _Kolide_ from Apps & Features 23 | 2. Depending on agent version installed, the uninstall will leave the prior launcher database in either `C:\Program Files\Kolide\Launcher-kolide-k2` or `C:\ProgramData\Kolide\Launcher-kolide-k2`. For a complete removal, these directories can be deleted through Windows Explorer or from an Admin PowerShell window with the following commands: 24 | 25 | - `Remove-Item -LiteralPath "C:\Program Files\Kolide\Launcher-kolide-k2" -Force -Recurse` 26 | - `Remove-Item -LiteralPath "C:\ProgramData\Kolide\Launcher-kolide-k2" -Force -Recurse` 27 | 28 | 3. (Optionally) Uninstall _WireGuard_ from Apps & Features 29 | 30 | === "Ubuntu" 31 | 1. Stop and remove Kolide and the related launch mechanisms 32 | ```bash 33 | sudo systemctl stop launcher.kolide-k2.service 34 | sudo systemctl disable launcher.kolide-k2.service 35 | ``` 36 | 2. Uninstall Kolide program files 37 | ```bash 38 | sudo apt(-get) remove launcher-kolide-k2 39 | ``` 40 | 3. Delete Kolide files & caches 41 | ```bash 42 | sudo rm -r /{etc,var}/kolide-k2 43 | ``` 44 | 45 | ## OS-agnostic uninstall steps 46 | 47 | When the program has been removed from your device, let an admin know in [#naisdevice](https://nav-it.slack.com/archives/C013XV66XHB) Slack channel. 48 | This is necessary so that the record of your device can be purged from our Kolide systems. Autoremoval will occur after 29 days. 49 | -------------------------------------------------------------------------------- /docs/operate/naisdevice/how-to/update.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [naisdevice, how-to] 3 | --- 4 | 5 | # Update naisdevice 6 | 7 | === "macOS" 8 | 9 | {% if tenant() == "nav" %} 10 | 1. Request privileges by running `Privileges.app` 11 | {% endif %} 12 | 2. Open a Terminal window. 13 | 3. Run the following command: 14 | ```bash 15 | brew update && brew upgrade <> 16 | ``` 17 | 18 | === "Windows (Scoop)" 19 | 20 | 1. Open a Terminal window. 21 | 2. Run the following command: 22 | ```powershell 23 | scoop update <> 24 | ``` 25 | 26 | === "Windows (Manual)" 27 | 28 | 1. Open a browser. 29 | 2. Go to [github.com/nais/device](https://github.com/nais/device/releases/latest). 30 | 3. Download and run the newest `<>.exe` installer. 31 | 32 | === "Ubuntu" 33 | 34 | 1. Open a Terminal window. 35 | 2. Run the following command: 36 | ```bash 37 | apt install --only-upgrade <> 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/persistence/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 💡 Explanations: explanations 4 | - ... 5 | -------------------------------------------------------------------------------- /docs/persistence/bigquery/.pages: -------------------------------------------------------------------------------- 1 | title: BigQuery 2 | nav: 3 | - README.md 4 | - 🎯 How-To: how-to 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/persistence/bigquery/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [persistence, bigquery, explanation, services] 3 | --- 4 | 5 | # Google Cloud BigQuery Dataset 6 | 7 | Google Cloud BigQuery is a service that provides a relational database that is optimized for analytical workloads. It is a good choice for storing data that is relational in nature. 8 | 9 | Nais provides BigQuery for storing and working with analytical datasets as a 10 | managed service through Google Cloud Platform. This page describes how to get 11 | started with BigQuery for your applications. 12 | 13 | ## Nais Application yaml manifest options 14 | 15 | Full documentation of all available options can be found over at: [`spec.gcp.bigQueryDatasets[]`](../../workloads/application/reference/application-spec.md#gcpbigquerydatasets). 16 | 17 | ## Caveats 18 | 19 | === "Automatic Deletion" 20 | Once a BigQuery Dataset is provisioned, it will not be automatically deleted - unless one explicitly sets [`spec.gcp.bigQueryDatasets[].cascadingDelete`](../../workloads/application/reference/application-spec.md#gcpbigquerydatasetscascadingdelete) to `true`. 21 | Clean up is done by deleting application resource and deleting the BigQuery instance directly in [console.cloud.google.com](https://console.cloud.google.com/bigquery). 22 |
23 | When there exist no tables in the specified BigQuery Dataset, deleting the "nais application" will delete the whole BigQuery Dataset, even if [`spec.gcp.bigQueryDatasets[].cascadingDelete`](../../workloads/application/reference/application-spec.md#gcpbigquerydatasetscascadingdelete) is set to `false`. 24 | === "Unique names" 25 | The name of your Dataset must be unique within your team's GCP project. 26 | === "Updates/Immutability" 27 | The NAIS Manifest does not currently support updating any setting of existing BigQuery Datasets. 28 | === "K8s resource naming" 29 | Since Kubernetes does not permit underscores (`_`) in the names of any K8s resource, any underscores will be converted to hyphens (`-`). 30 | 31 | ## Example with all configuration options 32 | 33 | See [full example](../../workloads/application/reference/application-example.md). 34 | -------------------------------------------------------------------------------- /docs/persistence/bigquery/how-to/connect.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, bigquery] 3 | --- 4 | 5 | # Using BigQuery from your application 6 | 7 | When connecting your BigQuery client you need to specify the project ID and the dataset ID. 8 | The project ID is available in the `GCP_TEAM_PROJECT_ID` environment variable. 9 | There's no automatic environment variable for the dataset ID. 10 | 11 | See the [BigQuery documentation](https://cloud.google.com/bigquery/docs/samples) for examples on how to use BigQuery with your language of choice. 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/persistence/bigquery/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, bigquery] 3 | --- 4 | 5 | # Create an instance of BigQuery 6 | 7 | Below is a minimal working example for a Nais Application manifest. 8 | 9 | ## 1. Create dataset 10 | ???+ note ".nais/app.yaml" 11 | 12 | ```yaml 13 | apiVersion: "nais.io/v1alpha1" 14 | kind: "Application" 15 | metadata: 16 | name: 17 | ... 18 | spec: 19 | ... 20 | gcp: 21 | bigQueryDatasets: 22 | - name: 23 | permission: READWRITE 24 | ``` -------------------------------------------------------------------------------- /docs/persistence/buckets/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/persistence/buckets/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [bucket, services, explanation] 3 | --- 4 | 5 | # Buckets 6 | 7 | A bucket is a storage container for objects. 8 | Objects are files that contain data, such as documents, images, videos, and application code. 9 | 10 | Nais supports provisioning and managing buckets in Google Cloud Storage (GCS) for use by your applications. 11 | -------------------------------------------------------------------------------- /docs/persistence/buckets/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, bucket] 3 | --- 4 | 5 | # Create a bucket 6 | 7 | This guide will show you how to create a Google Cloud Storage bucket. 8 | 9 | ## Add the bucket to the Nais application manifest 10 | 11 | You create the bucket through the Nais application manifest. 12 | 13 | !!! warning "Use a globally unique name" 14 | 15 | Bucket names must be globally unique across the entire Google infrastructure. 16 | 17 | ```yaml 18 | apiVersion: nais.io/v1alpha1 19 | kind: Application 20 | metadata: 21 | name: 22 | ... 23 | spec: 24 | ... 25 | gcp: 26 | buckets: 27 | - name: 28 | retentionPeriodDays: 30 29 | lifecycleCondition: 30 | age: 7 31 | createdBefore: 2020-01-01 32 | daysSinceCustomTime: 2 33 | numNewerVersions: 2 34 | withState: ANY 35 | ``` 36 | 37 | `retentionPeriodDays` and `lifecycleCondition` are for necessary for [backup](../reference/README.md). 38 | 39 | ## Deploy your manifest 40 | 41 | Deploy your manifest either using [Nais deploy action](../../../build/how-to/build-and-deploy.md), or manually: 42 | 43 | ```bash 44 | kubectl apply -f 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /docs/persistence/buckets/how-to/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [bucket, how-to] 3 | --- 4 | # Deleting a bucket 5 | 6 | Delete unused buckets to avoid incurring unnecessary costs. A bucket is deleted by enabling cascading deletion, and deleting the application. 7 | 8 | ## Enable cascading/automatic deletion 9 | 10 | For deletion of the application to automatically delete the bucket, set `cascadingDelete` to `true` in your Nais application manifest. Don't worry, the bucket won't be deleted if it contains files. 11 | 12 | ```yaml hl_lines="11" 13 | apiVersion: nais.io/v1alpha1 14 | kind: Application 15 | metadata: 16 | name: 17 | ... 18 | spec: 19 | ... 20 | gcp: 21 | buckets: 22 | - name: 23 | cascadingDelete: true 24 | retentionPeriodDays: 30 25 | lifecycleCondition: 26 | age: 7 27 | createdBefore: 2020-01-01 28 | daysSinceCustomTime: 2 29 | numNewerVersions: 2 30 | withState: ANY 31 | ``` 32 | ## Delete your application 33 | 34 | Delete your application resource. 35 | 36 | ```bash 37 | kubectl delete application 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/persistence/buckets/reference/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Buckets reference 3 | tags: [reference, bucket] 4 | --- 5 | 6 | # Buckets reference 7 | 8 | ## Backup of a bucket 9 | 10 | There is no automatic backup enabled for buckets. I.e. the files can not be restored in the event of accidental deletion or storage system failure. 11 | 12 | ### Specification 13 | 14 | * `retentionPeriodDays` is set in number of days, if not set; no retention policy will be set and files can be deleted by application or manually. 15 | 16 | * `lifecycleCondition` can be set to verify which files/objects are subject to permanent deletion based on the conditions set. 17 | * `age` specifies days it has existed in the bucket before it can be deleted. 18 | * `createdBefore` specifies a date all files created before this date can be deleted. 19 | * `daysSinceCustomTime` specifies the number of days since the object's [custom time] before it can be deleted. 20 | * `numNewerVersions` specifies the number of revisions that must be kept, all older revisions can be deleted. 21 | * `withState` specifies which state (LIVE, ARCHIVED, ANY) the object must have before being subject to permanent deletion. 22 | 23 | `numNewerVersions` and `withState` are both subject to object versioning being set on objects, as unversioned objects do not have multiple versions and have state value LIVE. 24 | 25 | [custom time]: https://cloud.google.com/storage/docs/metadata#custom-time 26 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/.pages: -------------------------------------------------------------------------------- 1 | title: CloudSQL 2 | nav: 3 | - README.md 4 | - 💡 Explanations: explanations 5 | - 🎯 How-To: how-to 6 | - 📚 Reference: reference 7 | - ... 8 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/explanations/cloud-sql-credentials.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cloud SQL credentials 3 | tags: [postgres, credentials, explanation] 4 | --- 5 | 6 | Cloud SQL uses ConfigConnector/CNRM to create and manage all relevant resources (sqldatabase, sqlinstance, sqluser, credentials) for postgreSQL. 7 | When creating an application via your nais.yaml the database in your google project, along with other necessary resources, are created. 8 | The creation of the database takes about ten minutes, and the credential settings will be updated after the database is ready for use. 9 | 10 | !!! warning 11 | If you delete and recreate your app, new credentials will be created and a synchronization is needed. 12 | This process can take up to ten minutes. Using the workaround described below you can avoid this synchronization period. 13 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/explanations/cloud-sql-proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cloud SQL Proxy 3 | tags: [postgres, cloudsql, cloud, sql, proxy, explanation] 4 | --- 5 | 6 | !!! info 7 | For instances created before 2024-04-18 8 | 9 | The application will connect to the database using [Cloud SQL Proxy](https://cloud.google.com/sql/docs/postgres/sql-proxy), ensuring that the database communication happens in secure tunnel, authenticated with automatically rotated credentials. 10 | 11 | Nais will add and configure the proxy client container as a sidecar in the pod, making it available on `localhost` for the application. The application will then connect to the proxy using standard database protocol just as if it was the actual database. 12 | 13 | ![The diagram shows how the application connects to the database using Cloud SQL Proxy. Cloud SQL connects to an instance, the proxy server communicates with the proxy client using a TCP secure tunnel. The proxy client is a sidecar in the pod, available on the localhost for the application on the client machine.](../../../assets/sqlproxy.svg) 14 | 15 | For more detailed information, check out the [Cloud SQL Proxy documentation](https://cloud.google.com/sql/docs/postgres/sql-proxy) 16 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/explanations/grants-and-privileges.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Grants and privileges 3 | tags: [postgres, cli, access, grants, privileges, explanation] 4 | --- 5 | 6 | When using the [`nais postgres prepare`](../how-to/personal-access.md#prerequisites) command, the user is granted some privileges in the database. 7 | 8 | By default, the user is granted `SELECT` privileges on all tables and sequences in the default schema. 9 | 10 | With the `--all-privileges` flag, the user is granted `ALL` privileges on all tables and sequences in the default schema. 11 | In addition, the user is granted `CREATE` on the default schema. 12 | This should be enough to allow most maintenance tasks, but if you need more privileges, you can usually grant yourself the necessary privileges. 13 | 14 | However, making changes to the database is best done through the application or through database migration scripts (such as [Flyway](https://flywaydb.org/), [Liquibase](https://www.liquibase.org/), or [Alembic](https://alembic.sqlalchemy.org/)) that run as part of the application startup. 15 | 16 | Read more about PostgreSQL privileges in the official [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-grant.html). 17 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/certification-sync-issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Certification sync issues 3 | tags: [postgres, certificate, how-to, troubleshooting, debugging] 4 | --- 5 | 6 | If you have deleted your application and recreate it, there might be an issue that your new app will not be able to create a client certificate because the old one still exists. 7 | Your deploy may fail with an error message such as the one below: 8 | 9 | ``` 10 | MountVolume.SetUp failed for volume "sqeletor-sql-ssl-cert" : secret "sqeletor-" not found 11 | ``` 12 | 13 | This message can show up for a number of reasons (see our [troubleshooting guide](../../../workloads/how-to/troubleshooting.md)), so be sure to confirm that the certificate is the issue before proceeding. 14 | 15 | ```bash 16 | $ kubectl describe sqlsslcert -lapp= 17 | ``` 18 | 19 | Under `Events` you should see an error detailing the reason for the failure. 20 | If the error mentions an already existing certificate, you can delete it. 21 | 22 | To delete the database client certificate for your application, in Google Cloud Console navigate to [Cloud SQL instances](https://console.cloud.google.com/sql/instances) -> -> Connections -> Security, and then scroll down to _Manage client certificates_ and delete your certificate there. 23 | 24 | This can also be done using the `gcloud`-cli. 25 | 26 | ```bash 27 | $ gcloud sql ssl client-certs delete COMMON_NAME --instance=INSTANCE 28 | ``` 29 | 30 | _COMMON_NAME_ is usually equal to _INSTANCE_, which is usually equal to application name. 31 | The output of the `kubectl describe sqlsslcert` command you did earlier will contain the relevant values for _COMMON_NAME_ and _INSTANCE_. 32 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/change-tier.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Change the tier of your database instance 3 | tags: [postgres, tier, how-to] 4 | --- 5 | 6 | ## Select tier 7 | 8 | Choosing an appropriate tier depends on your application's requirements such as: 9 | 10 | - the amount of data you expect to store and query 11 | - the number of concurrent connections you expect to handle 12 | 13 | The tier you choose will affect the performance and cost of your database. 14 | 15 | See [the reference page for a list of available tiers](../reference/README.md#server-size). 16 | 17 | ## Change tier 18 | 19 | To change the tier, modify the `tier` field in your application manifest: 20 | 21 | ```yaml title="app.yaml" hl_lines="5" 22 | spec: 23 | gcp: 24 | sqlInstances: 25 | - type: POSTGRES_17 26 | tier: db-custom-1-3840 27 | databases: 28 | - name: mydb 29 | ``` 30 | 31 | Commit and push the changes to your application repository. 32 | 33 | The tier will be updated the next time you [deploy your application](../../../build/how-to/build-and-deploy.md). 34 | 35 | Updating the tier results in your database being restarted, which means it will be unavailable for up to a few minutes. 36 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/connect-to-cloned.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Connect to a cloned database 3 | tags: [postgres, connection, cloned, how-to] 4 | --- 5 | 6 | If you have for some reason cloned a database in the console, you need to do some manually changes on the new database to be allowed to connect to it with your. 7 | 8 | 1. Log in to the database with the old username and password 9 | 2. Run `GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "cloned-user";`, to give the new cloned user access to all the old tables. 10 | If you have objects outside of tables those also needs to be changed. 11 | 3. Delete the `google-sql-appname`-secret from the cluster (if it exists). 12 | This allow Naiserator to generate new secrets for the cloned database. 13 | 4. Update your `nais.yaml`-file to use the instance name of the cloned database instead of the old ones. 14 | 5. Delete the old database when you are finished. 15 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/debugging.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [postgres, debugging, troubleshooting, how-to] 3 | --- 4 | 5 | # Debugging 6 | 7 | When issues arise with your [Cloud SQL instance](../explanations/cloud-sql-instance.md), you can use the following steps to troubleshoot the problem. 8 | 9 | Some times your application may look fine and work fine, but some update to the SQLInstance has not been properly applied. 10 | In these situations, inspecting the resources may reveal update problems. 11 | If there is a problem with updating the SQLInstance, no changes will be applied until the problem is resolved. 12 | 13 | ## Check the events and status on the [Config Connector](https://cloud.google.com/config-connector/docs/overview) resources 14 | 15 | ```text 16 | $ kubectl describe sqlinstance -lapp= 17 | $ kubectl describe sqldatabase -lapp= 18 | $ kubectl describe sqluser -lapp= 19 | $ kubectl describe sqlsslcert -lapp= 20 | ``` 21 | 22 | ## Check the logs of the Cloud SQL Proxy (if instance uses cloudsql-proxy) 23 | 24 | ```text 25 | $ kubectl logs -c cloudsql-proxy 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/delete-database.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deleting the database 3 | tags: [postgres, delete, database, how-to] 4 | --- 5 | 6 | The database is not automatically removed when deleting your Nais application. Remove unused databases to avoid incurring unnecessary costs. This is done by setting [cascadingDelete](../../../workloads/application/reference/application-spec.md#gcpsqlinstancescascadingdelete) in your `nais.yaml`-specification. 7 | 8 | !!! danger 9 | When you delete an Cloud SQL instance, you cannot reuse the name of the deleted instance until one week from the deletion date. 10 | 11 | To remove a database completely without deleting the application: 12 | 13 | 1. First, set [cascadingDelete](../../../workloads/application/reference/application-spec.md#gcpsqlinstancescascadingdelete) to `true` in the application spec and deploy it 14 | 2. Remove `sqlInstances` from the application spec and deploy again 15 | 16 | The database and the instance it runs on should now be completely removed after a short while. 17 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/existing-instance-private-ip.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Failing to assign private IP to an existing Cloud SQL instance 3 | tags: [postgres, private-ip, how-to, troubleshooting, debugging] 4 | --- 5 | 6 | If you have deleted your application and recreate it, there might be an issue that your new app will not be able to create a client certificate because the old one still exists. 7 | Your deploy may fail with an error message such as the one below: 8 | 9 | ``` 10 | MountVolume.SetUp failed for volume "sqeletor-sql-ssl-cert" : secret "sqeletor-" not found 11 | ``` 12 | 13 | This message can show up for a number of reasons (see our [troubleshooting guide](../../../workloads/how-to/troubleshooting.md)), so be sure to confirm that the certificate is the issue before proceeding. 14 | 15 | ```bash 16 | $ kubectl describe sqlsslcert -lapp= 17 | ``` 18 | 19 | Under `Events` you should see an error detailing the reason for the failure. 20 | If you see a message that says `Cannot assign a private IP address for an existing Cloud SQL instance in a Shared VPC`, 21 | the problem is that the deletion of the application resulted in a bit of information being lost, which causes nais to attempt to assign a private IP to the instance. 22 | 23 | An [SQLInstance](../explanations/cloud-sql-instance.md) created before 2024-04-18 will have a public IP address, and can not be updated to have a private IP address. 24 | This error occurs when the SQLInstance resource in the cluster has been deleted, without the corresponding instance actually being deleted in GCP. 25 | In this case, nais is unable to detect that the instance has a public IP, and will attempt to assign a private IP, which is not possible. 26 | 27 | The solution is to edit the SQLInstance resource in the cluster and removing the `ipConfiguration` stanzas: 28 | `kubectl patch sqlinstance -n --type json -p='[{"op": "remove", "path": "/spec/settings/ipConfiguration/privateNetworkRef"}]'`. 29 | After a few minutes the issue will be resolved and the secrets will be created. 30 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/password-sync-issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Workaround for password synchronization issues 3 | tags: [postgres, password, credentials, how-to] 4 | --- 5 | 6 | We recommend using [nais-cli] for rotating password for your Postgres database user. 7 | 8 | ```bash 9 | nais postgres password rotate appname 10 | ``` 11 | 12 | ### Manually 13 | 14 | Retrieve the password from the secret google-sql-`MYAPP` in your namespace (the password is base64 encoded): 15 | 16 | ```shell 17 | kubectl get secret google-sql- -o jsonpath="{ .data[''] }" | base64 -d 18 | ``` 19 | 20 | Log in to the Google [Cloud Console](https://console.cloud.google.com) and set the password manually for the application user in the sql instance: 21 | SQL -> `DB_INSTANCE` -> Users -> `USERNAME` -> Change password 22 | 23 | [nais-cli]: ../../../operate/cli/how-to/install.md 24 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/reset-database-credentials.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reset database credentials 3 | tags: [postgres, password, credentials, how-to] 4 | --- 5 | 6 | !!! info 7 | If you have multiple sql users their names will be on the format: `--` instead of `` 8 | 9 | To reset the database credentials for your application (if application name, database name or envVarPrefix has been changed), you need to first delete the secret and sqluser for the database: 10 | 11 | ```bash 12 | $ kubectl --namespace delete secret google-sql- 13 | $ kubectl --namespace delete sqluser 14 | ``` 15 | 16 | Then either redeploy your application or force a synchronization of your application: 17 | 18 | ```bash 19 | kubectl --namespace patch application -p '[{"op": "remove", "path": "/status/synchronizationHash"}]' --type=json 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/persistence/cloudsql/how-to/upgrade-postgres.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Upgrade major version 3 | tags: [postgres, upgrade, how-to] 4 | --- 5 | 6 | This page describes how to upgrade the major version of your PostgreSQL database. 7 | 8 | ## Preparations 9 | 10 | Before doing a major version upgrade, consult the [Google Cloud SQL documentation](https://cloud.google.com/sql/docs/postgres/upgrade-major-db-version) for any preparation that needs to be done. 11 | 12 | !!! warning 13 | 14 | Upgrading requires the instance to become unavailable for a period of time, depending on the size of your database. 15 | Expect a downtime of **10 minutes or more**. 16 | 17 | We recommend that you schedule your upgrade to a time when your application can be offline. 18 | 19 | ## Choose a new major version 20 | 21 | Select a new major version of PostgreSQL that you want to upgrade to. 22 | For safe upgrades, it is recommended to only do one major version at a time. 23 | 24 | The full list of supported versions can be found in the [application spec reference](../../../workloads/application/reference/application-spec.md#gcpsqlinstancestype). 25 | 26 | ## Change the major version 27 | 28 | To change the major version, modify the `type` field in your application manifest: 29 | 30 | ```yaml title="app.yaml" hl_lines="4" 31 | spec: 32 | gcp: 33 | sqlInstances: 34 | - type: POSTGRES_17 35 | ``` 36 | 37 | Commit and push the changes to your application repository. 38 | 39 | The upgrade will start the next time you [deploy your application](../../../build/how-to/build-and-deploy.md). 40 | -------------------------------------------------------------------------------- /docs/persistence/kafka/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 💡 Explanations: explanations 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | - ... 7 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/access-from-non-nais.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [kafka, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Accessing topics from an application outside Nais 7 | 8 | This guide will show you how to access a [Kafka topic](create.md) from an application outside Nais clusters. 9 | 10 | ## Enable access to the relevant pool in your manifest 11 | 12 | ???+ note ".nais/aivenapp.yaml" 13 | 14 | ```yaml 15 | apiVersion: aiven.nais.io/v1 16 | kind: AivenApplication 17 | metadata: 18 | name: 19 | namespace: 20 | spec: 21 | kafka: 22 | pool: (TODO: link to available tenant pools) 23 | secretName: 24 | protected: true 25 | ``` 26 | 27 | !!! info 28 | The secretName must be a valid [DNS label](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names), and must be unique within the namespace. 29 | 30 | ## Apply the AivenApplication 31 | === "Automatically" 32 | Add the file to your application repository, alongside `nais.yaml` to deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 33 | === "Manually" 34 | ```bash 35 | kubectl apply -f ./nais/aivenapp.yaml --namespace= --context= 36 | ``` 37 | 38 | ## Extract the value of the generated secret 39 | ```bash 40 | kubectl get secret --namespace --contect -o jsonpath='{.data}' 41 | ``` 42 | 43 | Make the values available to your application. 44 | 45 | ## Grant access to the topic 46 | 47 | The owner of the topic must [grant your application access to the topic](manage-acl.md). 48 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/access.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, kafka] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Accessing topics from an application 7 | 8 | This guide shows you how to access Kafka topics from your application. 9 | 10 | ## Prerequisites 11 | 12 | You need an existing topic to access. See [Create a Kafka topic](create.md) for how to create a topic. 13 | 14 | ## Enable access to the relevant pool in your workload definition 15 | 16 | ???+ note ".nais/app.yaml" 17 | 18 | ```yaml 19 | apiVersion: nais.io/v1alpha1 20 | kind: Application 21 | metadata: 22 | name: 23 | namespace: 24 | labels: 25 | team: 26 | spec: 27 | kafka: 28 | pool: 29 | ``` 30 | 31 | Select a `pool` from one of the [available pools](../reference/pools.md). 32 | 33 | ## Grant access to the topic 34 | 35 | The owner of the topic must [grant your application access to the topic](manage-acl.md). 36 | 37 | ## Configure your application 38 | 39 | Aiven has written several articles on how to configure your application. 40 | We use SSL, so ignore the SASL-SSL examples: 41 | 42 | - [Java](https://aiven.io/docs/products/kafka/howto/connect-with-java) 43 | - [Python](https://aiven.io/docs/products/kafka/howto/connect-with-python) 44 | - [Node.js](https://aiven.io/docs/products/kafka/howto/connect-with-nodejs) 45 | - [Go](https://aiven.io/docs/products/kafka/howto/connect-with-go) 46 | 47 | For all available environment variables, see the [reference](../reference/environment-variables.md). 48 | 49 | We recommend following the [application design guidelines](../README.md#application-design-guidelines) for how to configure your application. 50 | 51 | ## Apply the application 52 | === "Automatically" 53 | Add the file to your application repository to deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 54 | === "Manually" 55 | ```bash 56 | kubectl apply -f ./nais/app.yaml --namespace= --context= 57 | ``` 58 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, kafka] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Create a Kafka topic 7 | 8 | This guide will show you how to create a Kafka topic. 9 | 10 | The fully qualified topic name is the name of the `Topic` resource prefixed with your team namespace: 11 | 12 | ``` 13 | . 14 | ``` 15 | 16 | This name is also set in the `.status.fullyQualifiedName` field on your Topic resource once the Topic is synchronized to Aiven. 17 | 18 | ## Creating topics 19 | 20 | ???+ note ".nais/topic.yaml" 21 | ```yaml hl_lines="4-5 7 9 11-14" 22 | apiVersion: kafka.nais.io/v1 23 | kind: Topic 24 | metadata: 25 | name: 26 | namespace: 27 | labels: 28 | team: 29 | spec: 30 | pool: 31 | acl: 32 | - team: 33 | application: 34 | access: readwrite # read, write, readwrite 35 | ``` 36 | 37 | Select a `pool` from one of the [available pools](../reference/pools.md). 38 | 39 | See the [Kafka topic reference](../reference/kafka-topic-spec.md) for a complete list of available options. 40 | 41 | ## Grant access to the topic for other applications (optional) 42 | 43 | See [manage access](manage-acl.md) for how to grant access to your topic. 44 | 45 | ## Apply the Topic resource 46 | 47 | === "Automatically" 48 | Add the file to your application repository to deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 49 | === "Manually" 50 | ```bash 51 | kubectl apply -f ./nais/topic.yaml --namespace= --context= 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, kafka, delete, annotate] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Delete Kafka topic and data 7 | 8 | !!! warning 9 | Permanent deletes are irreversible. Do this only as a step to completely remove your data. 10 | 11 | When you want to delete a Kafka topic and it's data, the `Topic` resource in Nais needs to be annotated. 12 | 13 | ## Enable data deletion 14 | 15 | Start with annotating the `Topic` resource with `kafka.nais.io/removeDataWhenResourceIsDeleted=true` using `kubectl annotate`. 16 | 17 | ``` bash 18 | kubectl annotate topic --namespace= --context= kafka.nais.io/removeDataWhenResourceIsDeleted=true 19 | ``` 20 | 21 | When this annotation is in place, deleting the topic resource from Kubernetes will also delete the Kafka topic and all of its data. 22 | 23 | ## Delete the topic resource 24 | 25 | ```bash 26 | kubectl delete topic --namespace= --context= 27 | ``` 28 | 29 | Remember to delete the `Topic` resource from your Git repository. 30 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/internal.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Kafka Streams with internal topics 3 | tags: [how-to, kafka] 4 | conditional: [not-test-nais] 5 | --- 6 | 7 | # Using Kafka Streams with internal topics 8 | 9 | <> 10 | 11 | This guide will show you how to use [Kafka Streams](https://kafka.apache.org/documentation/streams/) with internal topics. 12 | 13 | ## Enable Kafka Streams in your application 14 | ???+ note ".nais/app.yaml" 15 | 16 | ```yaml hl_lines="11" 17 | apiVersion: nais.io/v1alpha1 18 | kind: Application 19 | metadata: 20 | name: 21 | namespace: 22 | labels: 23 | team: 24 | spec: 25 | kafka: 26 | pool: 27 | streams: true 28 | ``` 29 | 30 | Select a `pool` from one of the [available pools](../reference/pools.md). 31 | 32 | ## Configure your application 33 | 34 | When you do this you **must** configure Kafka Streams by setting the property `application.id` to a value that starts 35 | with the value of the env var `KAFKA_STREAMS_APPLICATION_ID`, which will be injected into your pod automatically. 36 | 37 | ## Apply the application 38 | 39 | === "Automatically" 40 | Add the file to your application repository to deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 41 | === "Manually" 42 | ```bash 43 | kubectl apply -f ./nais/app.yaml --namespace= --context= 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/manage-acl.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, kafka] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Manage access 7 | 8 | This guide will show you how to manage access to your topic. 9 | 10 | ## Prerequisites 11 | 12 | - [An existing topic](create.md) to manage access to. 13 | 14 | ## Add ACLs to your topic 15 | 16 | !!! info 17 | It is possible to use simple wildcards (`*`) in both team and application names, which matches any character any number of times. 18 | Be aware that due to the way ACLs are generated and length limits, the ends of long names can be cut, eliminating any wildcards at the end. 19 | 20 | Example of various ACLs: 21 | 22 | ???+ note ".nais/topic.yaml" 23 | 24 | ```yaml 25 | ... 26 | apiVersion: nais.io/v1alpha1 27 | kind: Topic 28 | ... 29 | spec: 30 | acl: 31 | - team: 32 | application: 33 | access: read 34 | - team: 35 | application: 36 | access: read 37 | - team: 38 | application: 39 | access: write 40 | - team: 41 | application: 42 | access: write 43 | - team: 44 | application: * 45 | access: read # ALL applications from this trusted-team has read 46 | - team: * 47 | application: 48 | access: read # Applications named from ANY team has read 49 | - team: 50 | application: rapid-* 51 | access: readwrite # ALL applications from with names starting with `rapid-` has readwrite access 52 | ... 53 | ``` 54 | 55 | ## Apply the Topic resource 56 | === "Automatically" 57 | Add the file to your application repository to deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 58 | === "Manually" 59 | ```bash 60 | kubectl apply -f ./nais/topic.yaml --namespace= --context= 61 | ``` 62 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/remove-access.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, kafka] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Remove access to topics from an application 7 | This guide will show you how to remove your application's access to a Kafka topic. 8 | 9 | ## Remove ACLs from the topic 10 | [Remove the ACL](manage-acl.md) that grants your application access to the topic. 11 | 12 | ## Remove the kafka resource from your application 13 | ???+ note ".nais/app.yaml" 14 | 15 | ```yaml hl_lines="9-10" 16 | apiVersion: nais.io/v1alpha1 17 | kind: Application 18 | metadata: 19 | name: 20 | namespace: 21 | labels: 22 | team: 23 | spec: 24 | kafka: 25 | pool: # TODO: link to available tenant pools 26 | ``` 27 | 28 | ## Apply the application 29 | === "Automatically" 30 | Add the file to your application repository to deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 31 | === "Manually" 32 | ```bash 33 | kubectl apply -f ./nais/app.yaml --namespace= --context= 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/renew-credentials-for-non-nais.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [kafka, how-to] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Renew credentials for non-Nais applications 7 | 8 | Eventually the credentials created in [Accessing topics from an application outside Nais](access-from-non-nais.md) will expire. 9 | Well in advance of this, Aiven will issue a notification to the technical contacts, and we route those to the slack channel [#aiven-driftsmeldinger](https://nav-it.slack.com/archives/C01TT8SS4LA). 10 | 11 | When it is time to renew the credentials, follow these steps: 12 | 13 | ## Edit the AivenApplication resource 14 | 15 | You need to change the `.spec.(kafka|openSearch|valkey[]).secretName` field in the `AivenApplication` resource you used to create the credentials in the first place. 16 | Make a note of the current value, and change it to something suitable. 17 | You can use any valid name you want, but make sure it is different from the old name. 18 | 19 | ## Wait for a new secret to appear 20 | 21 | When you save/apply the changed secret name, new credentials are generated. 22 | When complete, a secret with the requested name will become available in the cluster. 23 | 24 | ## Extract updated credentials 25 | 26 | Extract the credentials from the newly created secret, in the same way as you originally did when you first created the `AivenApplication` resource. 27 | 28 | ```bash 29 | kubectl get secret --namespace --contect -o jsonpath='{.data}' 30 | ``` 31 | 32 | Make the values available to your application. 33 | 34 | ## Clean up 35 | 36 | When your application has been updated to use the new credentials and you see that everything is working, delete the old secret. 37 | 38 | ```bash 39 | kubectl delete secret --namespace --context 40 | ``` 41 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/tiered-storage.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, kafka, tiered-storage] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # How to turn on Tiered Storage for your Kafka topic 7 | 8 | This guide shows you how to enable tiered storage for your Kafka topic. 9 | 10 | ## Prerequisites 11 | 12 | You need to own an existing topic in nais. 13 | Check [Create a Kafka topic](create.md) for how to create a topic. 14 | 15 | Your topic can not use `compact` cleanup policy. 16 | 17 | ## Enable tiered storage by specifying local retention on a topic 18 | 19 | ???+ note "Git diff showing how to enable tiered storage in a 'nai example_topic.yaml' file" 20 | 21 | ```diff 22 | diff --git a/example_topic.yaml b/example_topic.yaml 23 | index 230ec001..cbc01774 100644 24 | --- a/example_topic.yaml 25 | +++ b/example_topic.yaml 26 | @@ -8,3 +8,8 @@ labels: 27 | spec: 28 | kafka: 29 | # ... other configuration ... 30 | + config: 31 | + # Must be a value smaller than `retentionHours` 32 | + localRetentionHours: X 33 | + # Must be a value smaller than `retentionBytes` 34 | + localRetentionBytes: Y 35 | ``` 36 | 37 | ## Apply the new configuration 38 | === "Automatically" 39 | Add the file to your application repository and deploy with [Nais github action](../../../build/how-to/build-and-deploy.md). 40 | === "Manually" 41 | ```bash 42 | kubectl apply -f ./example_topic.yaml --namespace= --context= 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/persistence/kafka/how-to/troubleshoot.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [kafka, troubleshooting, debugging, how-to] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Troubleshooting 7 | 8 | ## Topic authorization failed for topics 9 | 10 | When you get a topic authorization failed error in your application, it means that the application has authenticated correctly with the cluster, but does not have the necessary permissions to access the topic. 11 | 12 | This can happen for a number of reasons: 13 | 14 | ### The application is not listed in the ACLs for the topic. 15 | 16 | * Check that the application is listed with correct namespace and application name 17 | * Check that the application has the correct permissions for the topic 18 | 19 | ### In rare cases, the Kafka cluster may not have received the ACLs update by the time your application connects. 20 | 21 | * Make sure your application retries the operation after a short delay 22 | * If the problem persists, contact the nais team for assistance 23 | 24 | ## Testing your application 25 | 26 | To test that you have configured your consumer application correctly, you can use one of the kafkarator-canary topics. 27 | All applications (from all teams) have read access to the canary topics. 28 | All the canary topics receives messages on a fixed interval, containing a RFC3339 formatted timestamp. 29 | The only difference between each, is where the producer is located. 30 | The available canary topics are: 31 | 32 | | Pool | Topic name | 33 | | :------- | :-------------------------------------- | 34 | | nav-dev | nais-verification.kafka-canary-dev-gcp | 35 | | nav-dev | nais-verification.kafka-canary-dev-fss | 36 | | nav-prod | nais-verification.kafka-canary-prod-gcp | 37 | | nav-prod | nais-verification.kafka-canary-prod-fss | 38 | -------------------------------------------------------------------------------- /docs/persistence/kafka/reference/kafka-topic-example.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [kafka, reference] 3 | --- 4 | 5 | # Nais Topic example YAML 6 | 7 | 13 | 14 | This is a complete example of an `Topic` resource, commonly known as the `topic.yaml` file. 15 | 16 | For an in-depth explanation of each field, head over to the [reference documentation](./kafka-topic-spec.md). 17 | ``` yaml 18 | apiVersion: kafka.nais.io/v1 19 | kind: Topic 20 | metadata: 21 | creationTimestamp: null 22 | labels: 23 | team: myteam 24 | name: mytopic 25 | namespace: myteam 26 | spec: 27 | acl: 28 | - access: read 29 | application: consumer 30 | team: otherteam 31 | - access: write 32 | application: producer 33 | team: myteam 34 | - access: readwrite 35 | application: processor 36 | team: myteam 37 | config: 38 | cleanupPolicy: delete 39 | deleteRetentionHours: 24 40 | localRetentionBytes: 1000 41 | localRetentionHours: 68 42 | maxCompactionLagMs: 60000 43 | maxMessageBytes: 1048588 44 | minCompactionLagMs: 10000 45 | minimumInSyncReplicas: 2 46 | partitions: 1 47 | replication: 3 48 | retentionBytes: 6000 49 | retentionHours: 168 50 | segmentHours: 168 51 | pool: dev-nais-dev 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/persistence/kafka/reference/pools.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [kafka, reference] 3 | conditional: [not-test-nais] 4 | --- 5 | 6 | # Kafka Pools 7 | 8 | This is a list of available Kafka pools for [topics](../how-to/create.md) and [applications](../how-to/access.md). 9 | 10 | {% if tenant() == "nav" %} 11 | 12 | Topic resources can only be specified in GCP clusters. 13 | Applications can access topics from any cluster, including on-premises. 14 | 15 | Use the `nav-dev` pool for development and `nav-prod` for production. 16 | 17 | | Pool | Min. replication | Max. replication | Topic declared in | Available from | 18 | |:---------------------|:-----------------|:-----------------|:------------------|:---------------------------------------------| 19 | | `nav-dev` | 2 | 3 | `dev-gcp` | `dev-gcp`, `dev-fss` | 20 | | `nav-prod` | 2 | 9 | `prod-gcp` | `prod-gcp`, `prod-fss` | 21 | 22 | {% else %} 23 | 24 | No Kafka pools available for your tenant. 25 | 26 | {% endif %} 27 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/.pages: -------------------------------------------------------------------------------- 1 | title: OpenSearch 2 | 3 | nav: 4 | - README.md 5 | - 🎯 How-To: how-to 6 | - 📚 Reference: reference 7 | - ... 8 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [opensearch, explanation, persistence, services] 3 | description: >- 4 | Nais provides managed search index services through OpenSearch as a drop-in 5 | replacement for Elasticsearch. 6 | --- 7 | 8 | # OpenSearch 9 | 10 | <> 11 | 12 | OpenSearch is a fork of Elasticsearch that is maintained by Amazon. It is a drop-in replacement for Elasticsearch, and is fully compatible with the Elasticsearch API. It is a community-driven project that is open source and free to use. 13 | 14 | OpenSearch is a distributed, RESTful search and analytics engine capable of solving search related use cases. It is a good choice for implementing search over documents. 15 | 16 | OpenSearch can index documents without storing them allowing you to save on storage space at the cost of not being able to retrieve the contents of the document. 17 | This enables patterns where you use OpenSearch as a way of indexing into other forms of persistence. 18 | Combining opensearch with a separate master data store such as PostgreSQL is a very common pattern. 19 | Using PosgreSQL with OpenSearch in this way gives you the same data durability and backup policies as you have with PostgreSQL. 20 | 21 | A very powerful pattern for OpenSearch is search and filter, also known as [faceted search](https://opensearch.org/docs/latest/aggregations/bucket/index/). 22 | 23 | Nais offers OpenSearch via [Aiven](https://aiven.io/). 24 | All OpenSearch instances on Aiven, regardless of plan, are backed up but there are no disaster backups outside of the provider. 25 | The serviceuser for any particular OpenSearch instance gets rotated regularly by the platform. 26 | {%- if tenant() == "nav" %} 27 | Aiven OpenSearch can be used by applications in all environments, but must be *defined* in a GCP cluster. 28 | {%- endif %} 29 | 30 | ## Next steps 31 | 32 | :dart: [Create OpenSearch](how-to/create.md) 33 | 34 | :dart: [Use OpenSearch in your workload](how-to/use-in-workload.md) 35 | 36 | :dart: [Delete OpenSearch](how-to/delete.md) 37 | 38 | :books: [OpenSearch reference](reference/README.md) 39 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/how-to/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - create.md 3 | - use-in-workload.md 4 | - delete.md 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, opensearch] 3 | --- 4 | 5 | # Create OpenSearch 6 | 7 | This guide will show you how to create a OpenSearch instance for your team using [Nais Console](../../../operate/console.md). 8 | 9 | ## Prerequisites 10 | 11 | - You're part of a [Nais team](../../../explanations/team.md) 12 | 13 | ## Steps 14 | 15 | 1. Open [Nais Console :octicons-link-external-16:](https://console.<>.cloud.nais.io) in your browser 16 | 2. Select your team 17 | 3. Select **OpenSearch** in the sidebar menu 18 | 4. Click the **Create OpenSearch** button 19 | 5. Fill in the form 20 | 6. Confirm by clicking the **Create OpenSearch** button 21 | 22 | Creating the OpenSearch instance will take a few minutes. 23 | The **Status** column will show you the current state. 24 | 25 | Grab a coffee or do the [xkcd compiling thing](https://xkcd.com/303/) while you wait. 26 | 27 | ## Next steps 28 | 29 | :dart: Learn how to [use OpenSearch in your workload](use-in-workload.md) 30 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/how-to/dashboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, opensearch, dashboard] 3 | --- 4 | 5 | # Get access to the dashboard 6 | 7 | Each OpenSearch instance in Aiven comes with a built-in dashboard for visualizing your data. 8 | To get access to this dashboard you need to follow these steps: 9 | 10 | {%- if tenant() == "nav" %} 11 | ## Prerequisites 12 | 13 | For production services, you need to have the `aiven-prod` gateway enabled in Naisdevice. 14 | This is done through [Just In Time Access (JITA)](../../../operate/naisdevice/explanations/jita.md). 15 | 16 | {%- endif %} 17 | 18 | ## Steps 19 | 20 | ### 1. Create a personal service account 21 | 22 | Create a personal temporary Aiven service account using [nais-cli](../../../operate/cli/README.md): 23 | 24 | ```shell 25 | nais aiven create opensearch \ 26 | \ 27 | \ 28 | --access \ 29 | --instance 30 | ``` 31 | 32 | where 33 | 34 | - `` is a descriptive name for the service account, e.g. your name or somesthing similar. 35 | - `` is the name of the team that owns the OpenSearch instance. 36 | - `` is one of the available [access levels](../reference/README.md#access-levels), such as `read`. 37 | 38 | ### 2. Retrieve credentials for service account 39 | 40 | Retrieve the dashboard URI, username, and password for the service account you just created: 41 | 42 | ```shell 43 | nais aiven get opensearch \ 44 | \ 45 | 46 | ``` 47 | 48 | where `` is the name of the Kubernetes secret created in the previous step. 49 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/how-to/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, opensearch] 3 | --- 4 | 5 | # Delete OpenSearch 6 | 7 | This page guides you through the steps required to delete an OpenSearch instance. 8 | 9 | ## Prerequisites 10 | 11 | - [You are a member of a Nais team](../../../explanations/team.md) 12 | - [You have set up command-line access](../../../operate/how-to/command-line-access.md) 13 | - Your OpenSearch instance is managed by Nais Console. 14 | - If you created your OpenSearch [via the legacy](create-legacy.md), see [Migrate opensearch management to Console](migrate-to-console.md). 15 | 16 | ## Steps 17 | 18 | ### 1. Remove references from workload manifests 19 | 20 | Ensure that all references to the opensearch instance are removed from your workload manifests: 21 | 22 | ```diff title="app.yaml" 23 | spec: 24 | - openSearch: 25 | - instance: 26 | - access: 27 | ``` 28 | 29 | ### 2. Delete the OpenSearch instance 30 | 31 | 1. Open [Nais Console](https://console.<>.cloud.nais.io) in your browser and select your team 32 | 2. Select the **OpenSearch** tab 33 | 3. Select the OpenSearch instance you want to delete 34 | 4. Click the **Delete OpenSearch** button 35 | 5. Confirm the deletion by typing the name of the OpenSearch instance and clicking the **Delete OpenSearch** button 36 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/how-to/upgrade-major-version.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, opensearch] 3 | --- 4 | 5 | # Upgrade major version 6 | 7 | When the OpenSearch instance was created, it was set up with the major version that was current at the time. 8 | You can upgrade the OpenSearch instance to a newer major version via Nais Console. 9 | 10 | Downgrading to an older major version is not supported. 11 | 12 | ## Prerequisites 13 | 14 | - You've previously created an OpenSearch instance using [Nais Console](create.md) 15 | - If you created your OpenSearch instance using the [legacy method](create-legacy.md), see [Migrate opensearch management to Console](migrate-to-console.md). 16 | 17 | ## Steps 18 | 19 | ### 1. Prepare for the upgrade 20 | 21 | Consult the [OpenSearch release notes](https://docs.opensearch.org/latest/breaking-changes/) to understand the changes in the new major version. 22 | 23 | Ensure that your workload is compatible with the new major version of OpenSearch. 24 | 25 | ### 2. Upgrade the OpenSearch instance 26 | 27 | 1. Open [Nais Console :octicons-link-external-16:](https://console.<>.cloud.nais.io) in your browser 28 | 2. Select your team 29 | 3. Select **OpenSearch** in the sidebar menu 30 | 4. Select the OpenSearch instance you want to upgrade 31 | 5. Click the **Edit OpenSearch** button 32 | 6. In the form, select the desired major version of OpenSearch 33 | 7. Confirm by clicking the **Save changes** button 34 | 35 | The upgrade process will take a few minutes. The **Status** column will show you the current state. 36 | 37 | When the status changes to `Running`, the upgrade is complete. 38 | 39 | ### 3. Verify that the upgrade was successful 40 | 41 | Verify that your workload is functioning as expected after the upgrade. 42 | -------------------------------------------------------------------------------- /docs/persistence/opensearch/how-to/use-in-workload.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, opensearch] 3 | --- 4 | 5 | # Use OpenSearch in your workload 6 | 7 | This guide will show you how to connect your workload to a previously created OpenSearch instance. 8 | 9 | ## Prerequisites 10 | 11 | - You're part of a [Nais team](../../../explanations/team.md) 12 | - You have previously [created a OpenSearch](create.md) for your team 13 | 14 | ## Steps 15 | 16 | ### 1. Add reference to OpenSearch instance in workload manifest 17 | 18 | In your workload manifest, add the following lines to reference the OpenSearch instance: 19 | 20 | ```yaml title="nais.yaml" hl_lines="2-4" 21 | spec: 22 | openSearch: 23 | instance: $NAME 24 | access: read # read | readwrite | write | admin 25 | ``` 26 | 27 | Replace `$NAME` with the name of your OpenSearch instance. 28 | If you [created your OpenSearch through the legacy method](create-legacy.md), exclude the `opensearch--` prefix. 29 | 30 | The `access` field defines the access level your workload will have to the OpenSearch instance. 31 | Choose the access level that fits your use case. 32 | 33 | See the available access levels in the [OpenSearch reference](../reference/README.md#access-levels). 34 | 35 | ### 2. Find OpenSearch environment variables 36 | 37 | When the workload is deployed, the Nais platform will inject the necessary environment variables to connect to the OpenSearch instance. 38 | 39 | See the available environment variables in the [OpenSearch reference](../reference/README.md#environment-variables). 40 | 41 | ### 3. Use a OpenSearch client library 42 | 43 | Use a OpenSearch client library to connect to the OpenSearch instance using the injected environment variables. 44 | 45 | You can find a non-exhaustive list of OpenSearch clients over at the official OpenSearch page: . 46 | -------------------------------------------------------------------------------- /docs/persistence/postgresql/.pages: -------------------------------------------------------------------------------- 1 | title: PostgreSQL 2 | nav: 3 | - README.md 4 | - 💡 Explanations: explanations 5 | - 🎯 How-To: how-to 6 | - 📚 Reference: reference 7 | - ... 8 | -------------------------------------------------------------------------------- /docs/persistence/postgresql/how-to/database-observability.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Postgres database metrics 3 | tags: [postgres, metrics, how-to] 4 | --- 5 | 6 | !!! warning "Experimental feature" 7 | This feature is an alpha feature, and is subject to API change, instability or removal. 8 | See the [main Postgres page](../README.md) for more information. 9 | 10 | 11 | All PostgreSQL databases running in the cluster export metrics using the [Prometheus postgres exporter](https://github.com/prometheus-community/postgres_exporter). 12 | 13 | ## Viewing Postgres metrics in Grafana 14 | 15 | To view Postgres metrics in your Grafana dashboard, you can use the normal cluster datasource. 16 | 17 | 1. Log on to [Grafana](<>d/postgres/postgres-overview). 18 | 2. Select desired datasource (aka environment), namespace and instance. 19 | 20 | 21 | ## Viewing other Postgres metrics in Grafana 22 | 23 | 1. Log on to [Grafana](<>). 24 | 2. Go to Drilldown -> Metrics. 25 | 3. Select desired datasource (aka environment). 26 | 4. Add a label filter with `namespace=pg-`. 27 | 5. Add a label filter with `cluster_name=`. 28 | 6. Explore available metrics. Metrics from postgres-exporter usually start with `pg_`. 29 | 7. You can also create your own dashboards using these metrics. 30 | 31 | -------------------------------------------------------------------------------- /docs/persistence/postgresql/how-to/debugging.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [postgres, debugging, troubleshooting, how-to] 3 | --- 4 | 5 | # Debugging 6 | 7 | !!! warning "Experimental feature" 8 | This feature is an alpha feature, and is subject to API change, instability or removal. 9 | See the [main Postgres page](../README.md) for more information. 10 | 11 | 12 | When issues arise with your [Postgres cluster](../explanations/postgres-cluster.md), you can use the following steps to troubleshoot the problem. 13 | 14 | Some times your application may look fine and work fine, but some update to the postgres cluster has not been properly applied. 15 | In these situations, inspecting the resources may reveal update problems. 16 | If there is a problem with updating the postgres cluster, the problem needs to be resolved before further changes can be applied. 17 | 18 | ## Check the events and status on the relevant Kubernetes resources 19 | 20 | ```text 21 | $ kubectl describe postgresql -n pg- -lapp= 22 | $ kubectl describe sts -n pg- -lapp= 23 | $ kubectl describe pod -n pg- -lapp= 24 | $ kubectl describe pvc -n pg- -lapp= 25 | $ kubectl describe secret -n -lapp= 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/persistence/postgresql/how-to/delete-database.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deleting the database 3 | tags: [postgres, delete, database, how-to] 4 | --- 5 | 6 | !!! warning "Experimental feature" 7 | This feature is an alpha feature, and is subject to API change, instability or removal. 8 | See the [main Postgres page](../README.md) for more information. 9 | 10 | The database is not automatically removed when deleting your Nais application. 11 | Remove unused databases to avoid incurring unnecessary costs. 12 | This is done by setting [allowDeletion](../../../workloads/application/reference/application-spec.md#postgresclusterallowdeletion) in your `nais.yaml`-specification. 13 | 14 | To remove a database completely without deleting the application: 15 | 16 | 1. First, set [allowDeletion](../../../workloads/application/reference/application-spec.md#postgresclusterallowdeletion) to `true` in the application spec and deploy it 17 | 2. Remove `postgres` from the application spec and deploy again 18 | 19 | The database and the instance it runs on should now be completely removed after a short while. 20 | -------------------------------------------------------------------------------- /docs/persistence/postgresql/how-to/upgrade-postgres.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Upgrade major version 3 | tags: [postgres, upgrade, how-to] 4 | --- 5 | 6 | !!! warning "Experimental feature" 7 | This feature is an alpha feature, and is subject to API change, instability or removal. 8 | See the [main Postgres page](../README.md) for more information. 9 | 10 | This page describes how to upgrade the major version of your PostgreSQL database. 11 | 12 | ## Preparations 13 | 14 | Before doing a major version upgrade, consult the [PostgreSQL Release Notes](https://www.postgresql.org/docs/release/) for any preparation that needs to be done. 15 | 16 | ## Choose a new major version 17 | 18 | Select a new major version of PostgreSQL that you want to upgrade to. 19 | For safe upgrades, it is recommended to only do one major version at a time. 20 | 21 | The full list of supported versions can be found in the [application spec reference](../../../workloads/application/reference/application-spec.md#postgresclustermajorversion). 22 | 23 | ## Change the major version 24 | 25 | To change the major version, modify the `majorVersion` field in your application manifest: 26 | 27 | ```yaml title="app.yaml" hl_lines="4" 28 | spec: 29 | postgres: 30 | cluster: 31 | majorVersion: "17" 32 | ``` 33 | 34 | Commit and push the changes to your application repository. 35 | 36 | The upgrade will start the next time you [deploy your application](../../../build/how-to/build-and-deploy.md). 37 | -------------------------------------------------------------------------------- /docs/persistence/valkey/.pages: -------------------------------------------------------------------------------- 1 | title: Valkey 2 | 3 | nav: 4 | - README.md 5 | - 🎯 How-To: how-to 6 | - 📚 Reference: reference 7 | - ... 8 | -------------------------------------------------------------------------------- /docs/persistence/valkey/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [persistence, explanation, valkey, redis, services] 3 | --- 4 | # Valkey 5 | 6 | <> 7 | 8 | Valkey is a key value database that is used for storing and querying data. 9 | It is a good choice for storing data that is not relational in nature and often used for caching. 10 | 11 | The service user used by your workload to access Valkey instances gets rotated on a regular basis. 12 | 13 | ## Next steps 14 | 15 | :dart: [Create Valkey](how-to/create.md) 16 | 17 | :dart: [Use Valkey in your workload](how-to/use-in-workload.md) 18 | 19 | :dart: [Delete Valkey](how-to/delete.md) 20 | 21 | :books: [Valkey reference](reference/README.md) 22 | -------------------------------------------------------------------------------- /docs/persistence/valkey/how-to/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - create.md 3 | - use-in-workload.md 4 | - delete.md 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/persistence/valkey/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, valkey, redis] 3 | --- 4 | 5 | # Create Valkey 6 | 7 | This guide will show you how to create a Valkey instance for your team using [Nais Console](../../../operate/console.md). 8 | 9 | ## Prerequisites 10 | 11 | - You're part of a [Nais team](../../../explanations/team.md) 12 | 13 | ## Steps 14 | 15 | 1. Open [Nais Console :octicons-link-external-16:](https://console.<>.cloud.nais.io) in your browser 16 | 2. Select your team 17 | 3. Select **Valkey** in the sidebar menu 18 | 4. Click the **Create Valkey** button 19 | 5. Fill in the form 20 | 6. Confirm by clicking the **Create Valkey** button 21 | 22 | Creating the Valkey instance will take a few minutes. 23 | The **Status** column will show you the current state. 24 | 25 | Grab a coffee or do the [xkcd compiling thing](https://xkcd.com/303/) while you wait. 26 | 27 | ## Next steps 28 | 29 | :dart: Learn how to [use Valkey in your workload](use-in-workload.md) 30 | -------------------------------------------------------------------------------- /docs/persistence/valkey/how-to/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, valkey, redis] 3 | --- 4 | 5 | # Delete Valkey 6 | 7 | This page guides you through the steps required to delete a Valkey instance. 8 | 9 | ## Prerequisites 10 | 11 | - [You are a member of a Nais team](../../../explanations/team.md) 12 | - Your Valkey instance is managed by Nais Console. 13 | - If you created your Valkey [explicitly](create-explicit.md), see [Migrate Valkey management to Console](migrate-to-console.md). 14 | 15 | ## Steps 16 | 17 | ### 1. Remove references from workload manifests 18 | 19 | Ensure that all references to the Valkey instance are removed from your workload manifests: 20 | 21 | ```diff title="app.yaml" 22 | spec: 23 | - valkey: 24 | - - instance: 25 | - access: 26 | ``` 27 | 28 | ### 2. Delete the Valkey instance 29 | 30 | 1. Open [Nais Console](https://console.<>.cloud.nais.io) in your browser and select your team 31 | 2. Select the **Valkey** tab 32 | 3. Select the Valkey instance you want to delete 33 | 4. Click the **Delete Valkey** button 34 | 5. Confirm the deletion by typing the name of the Valkey instance and clicking the **Delete Valkey** button 35 | -------------------------------------------------------------------------------- /docs/persistence/valkey/how-to/use-in-workload.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [how-to, valkey, redis] 3 | --- 4 | 5 | # Use Valkey in your workload 6 | 7 | This guide will show you how to connect your workload to a previously created Valkey instance. 8 | 9 | ## Prerequisites 10 | 11 | - You're part of a [Nais team](../../../explanations/team.md) 12 | - You have previously created a Valkey for your team, either: 13 | - [via Console](create.md), or 14 | - [explicitly](create-explicit.md) 15 | 16 | ## Steps 17 | 18 | ### 1. Add reference to Valkey instance in workload manifest 19 | 20 | In your workload manifest, add the following lines to reference the Valkey instance: 21 | 22 | ```yaml title="nais.yaml" hl_lines="2-4" 23 | spec: 24 | valkey: 25 | - instance: $NAME 26 | access: read # read | readwrite | write | admin 27 | ``` 28 | 29 | Replace `$NAME` with the name of your Valkey instance. 30 | If you created your Valkey explicitly, exclude the `valkey--` prefix. 31 | 32 | The `access` field defines the access level your workload will have to the Valkey instance. 33 | Choose the access level that fits your use case. 34 | 35 | See the available access levels in the [Valkey reference](../reference/README.md#access-levels). 36 | 37 | ### 2. Find Valkey environment variables 38 | 39 | When the workload is deployed, the Nais platform will inject the necessary environment variables to connect to the Valkey instance. 40 | 41 | See the available environment variables in the [Valkey reference](../reference/README.md#environment-variables). 42 | 43 | ### 3. Use a Valkey client library 44 | 45 | Use a Valkey client library to connect to the Valkey instance using the injected environment variables. 46 | Many Redis client libraries will also be compatible with Valkey. 47 | 48 | You can find a non-exhaustive list of Valkey clients over at the official Valkey page: . 49 | -------------------------------------------------------------------------------- /docs/services/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - CDN: cdn 4 | - secrets 5 | - feature-toggling.md 6 | - ... 7 | -------------------------------------------------------------------------------- /docs/services/README.md: -------------------------------------------------------------------------------- 1 | # Other services 2 | 3 | This section covers the rest of the Nais functionality that didn't fit into any other categories. 4 | 5 | It includes services such as: 6 | 7 | - [CDN](cdn/README.md) 8 | - [Secrets](secrets/README.md) 9 | - [Feature toggling](./feature-toggling.md) 10 | - [Anti-virus](antivirus.md) 11 | - [Vulnerabilities](vulnerabilities/README.md) 12 | - [Leader election](leader-election/README.md) 13 | -------------------------------------------------------------------------------- /docs/services/cdn/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/services/cdn/how-to/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - upload-assets.md 3 | - manage-assets.md 4 | - ... 5 | -------------------------------------------------------------------------------- /docs/services/cdn/how-to/manage-assets.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [cdn, how-to] 3 | --- 4 | 5 | # Manage CDN assets 6 | 7 | This how-to guide shows you how to list and manage assets on the [CDN](../README.md). 8 | 9 | In most cases you only need to upload new assets through the GitHub Action. 10 | In the rare case you need to manage the assets directly, you can do so through the Google Cloud Console. 11 | 12 | ## Prerequisites 13 | 14 | - You have previously [uploaded assets to the CDN](upload-assets.md). 15 | 16 | ## Find reference to bucket 17 | 18 | Assets are stored in a Google Cloud Bucket. 19 | To find the bucket name: 20 | 21 | 1. Open the [Nais console](https://console.<>.cloud.nais.io) in your browser. 22 | 2. Select your team. 23 | 3. Select the **Settings** tab. 24 | 4. Under the **Managed resources** section, look for the heading named **Team CDN bucket**. 25 | 5. Click the link (`nais-cdn-<>--`) to view the bucket in Google Cloud Console. 26 | 27 | ## List and manage assets through Google Cloud Console 28 | 29 | The bucket view in Google Cloud Console lists your team's uploaded assets. 30 | This might be useful to verify that your uploaded assets are present, or to delete unused or erroneously uploaded assets. 31 | 32 | Some other common tasks you can perform in the Google Cloud Console: 33 | 34 | - [View and edit object metadata](https://cloud.google.com/storage/docs/viewing-editing-metadata) 35 | - [Set Cache-Control headers](https://cloud.google.com/storage/docs/caching) (though this will be overwritten by the GitHub Action on the next upload) 36 | - [Delete objects](https://cloud.google.com/storage/docs/deleting-objects) 37 | -------------------------------------------------------------------------------- /docs/services/cdn/reference/upload-assets.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [cdn, upload, reference] 3 | title: CDN Upload Action 4 | --- 5 | 6 | This is the reference documentation for the [CDN Upload GitHub action](../how-to/upload-assets.md). 7 | 8 | ## Inputs 9 | 10 | The action accepts the following inputs: 11 | 12 | `team` 13 | 14 | : **Required**. Team name. 15 | 16 | `source` 17 | 18 | : **Required**. Source directory. 19 | 20 | `destination` 21 | 22 | : **Required**. Destination directory. 23 | 24 | `tenant` 25 | 26 | : **Optional**. Tenant name. 27 | 28 | Default value: `"nav"` 29 | 30 | `source_keep_parent_name` 31 | 32 | : **Optional**. Keep the parent directory name in the destination path. 33 | 34 | Default value: `true` 35 | 36 | `cache_invalidation` 37 | 38 | : **Optional**. Invalidate cached content after upload. 39 | 40 | Default value: `false` 41 | 42 | This is an asynchronous operation and may take up to 15 minutes after the action has run. 43 | Invalidation is intended for use in exceptional circumstances, not as part of your normal workflow. 44 | 45 | See also [Google's documentation on best practices for cache invalidation](https://cloud.google.com/cdn/docs/best-practices#invalidation). 46 | 47 | `no_cache_paths` 48 | 49 | : **Optional**. Comma separated list of paths that should not be cached. 50 | 51 | Default value: `` 52 | 53 | ## Outputs 54 | 55 | `uploaded` 56 | 57 | : List of successfully uploaded files. 58 | 59 | Available as `${{ steps..outputs.uploaded }}` 60 | For example: 61 | 62 | ```yaml 63 | - id: 'upload-cdn' 64 | name: Upload static files to NAV CDN 65 | uses: nais/deploy/actions/cdn-upload/v2@master 66 | ... 67 | ``` 68 | 69 | will be available in future steps as `${{ steps.upload-cdn.outputs.uploaded }}`. 70 | -------------------------------------------------------------------------------- /docs/services/leader-election/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - ... 5 | -------------------------------------------------------------------------------- /docs/services/secrets/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/services/secrets/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [secrets, explanation, services] 3 | --- 4 | 5 | # Secrets 6 | 7 | A secret is a piece of sensitive information that is used in a [workload](../../workloads/README.md). 8 | This can be a password, an API key, or any other information that should not be exposed to the public. 9 | 10 | Secrets are kept separate from the codebase and configuration files that are usually stored in version control. 11 | 12 | There are two types of secrets on the Nais platform: 13 | 14 |
15 | - :construction_worker: **Platform-provided secrets** 16 | 17 | --- 18 | _Platform-provided secrets_ are provisioned and managed by the platform. 19 | 20 | - These typically contain credentials used for integrating with services that Nais supports, such as databases, Kafka and so on. 21 | - You will generally not deal with these secrets as their values are automatically made available to your workloads at runtime. 22 |
23 | 24 |
25 | - :technologist: **User-defined secrets** 26 | 27 | --- 28 | _User-defined secrets_ are managed by you and your [team](../../explanations/team.md). 29 | 30 | - These are typically used for integrating with third-party services or APIs that are not provided by Nais, such as Slack or GitHub. 31 | - User-defined secrets can also be used to store sensitive information specific to your application, such as encryption keys or other private configuration. 32 |
33 | 34 | ## Related pages 35 | 36 | :dart: Learn how to [create and manage a secret in Nais Console](how-to/console.md) 37 | 38 | :dart: Learn how to [use a secret in your workload](how-to/workload.md) 39 | -------------------------------------------------------------------------------- /docs/services/secrets/how-to/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - console.md 3 | - workload.md 4 | - ... 5 | -------------------------------------------------------------------------------- /docs/services/secrets/how-to/console.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [secrets, how-to, console] 3 | --- 4 | 5 | # Create and manage secrets in Console 6 | 7 | This how-to guide shows you how to create and manage a [secret](../README.md) in the Nais Console. 8 | 9 | ## Prerequisites 10 | 11 | - You're part of a [Nais team](../../../explanations/team.md) 12 | 13 | ## List secrets 14 | 15 | 1. Open [Nais console :octicons-link-external-16:](https://console.<>.cloud.nais.io) in your browser 16 | 2. Select your team 17 | 3. Select the `Secrets` tab 18 | 19 | ## Create a secret 20 | 21 | 1. Click `Create Secret` 22 | 2. Select the environment you want to create the secret in 23 | 3. Enter a **name** for your secret 24 | 4. Click `Create` 25 | 5. Optionally, add one or more key-value pairs to your newly created secret 26 | 27 | ## Edit a secret 28 | 29 | 1. Select the secret you want to edit 30 | 2. Add, edit, or delete key-value pairs for the secret as desired 31 | 3. Click `Save` when you're satisfied with the changes 32 | 33 | After saving, any workloads using the secret will automatically restart to receive the updated secret values. 34 | 35 | ## Delete a secret 36 | 37 | 1. Select the secret you want to delete 38 | 2. Click the `Delete` button in the secret's details page 39 | 40 | You will be prompted to confirm the deletion. 41 | Once confirmed, the secret will be permanently deleted and no longer available to any workloads. 42 | 43 | ## Related pages 44 | 45 | :dart: Learn [how to use a secret in your workload](workload.md) 46 | -------------------------------------------------------------------------------- /docs/services/secrets/how-to/workload.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, how-to, secrets] 3 | --- 4 | 5 | # Use a secret in your workload 6 | 7 | This how-to guide shows you how to reference and use a [secret](../README.md) 8 | in your [workload](../../../workloads/README.md). 9 | 10 | A secret can be made available as environment variables or files, or both. 11 | 12 | ## Prerequisites 13 | 14 | - You're part of a [Nais team](../../../explanations/team.md) 15 | - You have previously [created a secret](console.md#create-a-secret) for your team 16 | - A Github repository where the Nais team has access 17 | - The repository contains a valid workload manifest (`nais.yaml`) 18 | 19 | ## Expose secret as environment variables 20 | 21 | 1. Add a reference to the secret in the workload's `nais.yaml` manifest. 22 | 23 | For a secret named `cool-cat`, the manifest should contain these additional lines: 24 | 25 | ```yaml title="nais.yaml" hl_lines="2-3" 26 | spec: 27 | envFrom: 28 | - secret: cool-cat 29 | ``` 30 | 31 | 2. Commit and push the changes to version control, and deploy your workload as usual. 32 | 3. Each key-value pair is now available in your workload's runtime as an environment variable. 33 | 34 | For example, for a key named `SOME_KEY`: 35 | 36 | ```shell 37 | SOME_KEY=some-value 38 | ``` 39 | 40 | ## Mount secret as files 41 | 42 | 1. Add a reference to the secret in the workload's `nais.yaml` manifest. 43 | 44 | For a secret named `cool-cat`, the manifest should contain these additional lines: 45 | 46 | ```yaml title="nais.yaml" hl_lines="2-4" 47 | spec: 48 | filesFrom: 49 | - secret: cool-cat 50 | mountPath: /var/run/secrets/cool-cat 51 | ``` 52 | 53 | 2. Commit and push the changes to version control, and deploy your workload as usual. 54 | 3. Each key-value pair is now available as a file in your workload the specified mount path, e.g: 55 | 56 | ```shell 57 | /var/run/secrets/cool-cat/ 58 | ``` 59 | 60 | For example, a key named `some-key` will be available as a file at the following path: 61 | 62 | ```shell 63 | /var/run/secrets/cool-cat/some-key 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/services/secrets/reference/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [secrets, reference] 3 | --- 4 | 5 | # Secrets reference 6 | 7 | This is the reference documentation for [secrets](../README.md) on the Nais platform. 8 | 9 | ## Console 10 | 11 | Visit [Nais Console :octicons-link-external-16:](https://console.<>.cloud.nais.io) to find and manage your team's user-defined secrets. 12 | 13 | ## Workloads 14 | 15 | Use a secret in your [workload](../../../workloads/README.md) by referencing them in your `nais.yaml` manifest. 16 | 17 | The secret can be made available as environment variables or files. 18 | 19 | ### Environment Variables 20 | 21 | ```yaml 22 | spec: 23 | envFrom: 24 | - secret: 25 | ``` 26 | 27 | See also: 28 | 29 | :books: [Application reference][application] 30 | 31 | :books: [NaisJob reference][naisjob] 32 | 33 | ### Files 34 | 35 | ```yaml 36 | spec: 37 | filesFrom: 38 | - secret: 39 | mountPath: /var/run/secrets/ 40 | ``` 41 | 42 | See also: 43 | 44 | :books: [Application reference][application] 45 | 46 | :books: [NaisJob reference][naisjob] 47 | 48 | [application]: ../../../workloads/application/reference/application-spec.md#envfromsecret 49 | [naisjob]: ../../../workloads/job/reference/naisjob-spec.md#envfromsecret 50 | -------------------------------------------------------------------------------- /docs/services/vulnerabilities/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/services/vulnerabilities/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [salsa, slsa, supply-chain, vulnerabilities, explanation] 3 | --- 4 | 5 | # Vulnerability insights and management 6 | 7 | Nais provides what you need to secure your software supply chain and manage vulnerabilities in your workloads. 8 | 9 | Get started by using our [GitHub Actions](how-to/sbom.md) to generate SBOMs and attestations for your workloads. 10 | 11 | Once this is in place, you can use the [Nais Console](../../operate/console.md) to view and manage vulnerabilities in your workloads. 12 | -------------------------------------------------------------------------------- /docs/services/vulnerabilities/how-to/sbom.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [attestation, sbom, how-to] 3 | --- 4 | 5 | # Generate SBOM 6 | 7 | Simply add [nais/docker-build-push](https://github.com/nais/docker-build-push) to your workflow. 8 | 9 | ```yaml 10 | - uses: nais/docker-build-push@v0 11 | id: docker-push 12 | with: 13 | team: myteam # required 14 | salsa: true # optional, defaults to true 15 | # ... other options removed for readability 16 | ``` 17 | 18 | ??? note Opt-out 19 | Opt-out from salsa 20 | 21 | If you want to opt-out from salsa you can set the salsa input to false 22 | 23 | ```yaml 24 | salsa: false 25 | ``` 26 | 27 | ### Attest sign 28 | 29 | The `nais/docker-build-push` action default push to Google Container Registry (GAR). 30 | If you want to push to another registry, you can use the [nais/attest-sign](https://github.com/nais/attest-sign) to generate sbom and sign the attestation. 31 | 32 | ```yaml 33 | - uses: nais/attest-sign@v1 34 | id: attest-sign 35 | with: 36 | image_ref: my-image@sha256:12345 # required 37 | sbom: my-image.json # optional 38 | # ... other options removed for readability 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/tags.md: -------------------------------------------------------------------------------- 1 | # Tags 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/tutorials/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - Hello Nais: hello-nais.md 4 | - ... -------------------------------------------------------------------------------- /docs/tutorials/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [tutorial] 3 | hide: 4 | - feedback 5 | - footer 6 | --- 7 | 8 | # Tutorials 9 | 10 | Tutorials are lessons that focuses on _learning by doing_. 11 | 12 | These give you hands-on experience with various parts of Nais, where we carefully guide you each step of the way. 13 | 14 |
15 | - :octicons-rocket-24:{ .lg .middle } [**Hello Nais**](./hello-nais.md) 16 | 17 | --- 18 | 19 | Get your first application up and running on Nais. 20 | 21 |
22 | -------------------------------------------------------------------------------- /docs/workloads/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 💡 Explanations: explanations 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | - application 7 | - job 8 | - ... 9 | -------------------------------------------------------------------------------- /docs/workloads/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, explanation] 3 | --- 4 | 5 | # Workloads 6 | 7 | A core functionality of Nais is enabling you to run the code you write. 8 | 9 | We support two types of workloads, _applications_ and _jobs_. 10 | 11 |
12 | 13 | - **Application** 14 | 15 | --- 16 | An _application_ is a used for long-running processes such as an API. 17 | 18 | [:bulb: Learn more about applications](application/README.md) 19 | 20 | - **Job** 21 | 22 | --- 23 | A _job_ is used for one-off or scheduled tasks meant to complete and then exit. 24 | 25 | [:bulb: Learn more about jobs](job/README.md) 26 | 27 |
28 | 29 | ## Related pages 30 | 31 | [:bulb: The workload runtime environment](explanations/environment.md) 32 | 33 | [:bulb: Good practices for your workloads](explanations/good-practices.md) 34 | 35 | [:bulb: Zero trust on Nais](explanations/zero-trust.md) 36 | -------------------------------------------------------------------------------- /docs/workloads/application/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 💡 Explanations: explanations 4 | - 🎯 How-To: how-to 5 | - 📚 Reference: reference 6 | - ... 7 | -------------------------------------------------------------------------------- /docs/workloads/application/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [application, explanation, workloads, services] 3 | --- 4 | 5 | # Application 6 | 7 | A Nais application lets you run one or more instances of a container image. 8 | 9 | An application is defined by its application manifest, which is a YAML file that describes how the application should be run and what resources it needs. 10 | 11 | Once the application manifest is applied, Nais will set up your application as specified. If you've requested resources, Nais will provision and configure your application to use those resources. 12 | 13 | ## Related pages 14 | 15 | [:bulb: Learn more about exposing your application](explanations/expose.md) 16 | 17 | [:dart: Create an application](how-to/create.md) 18 | 19 | [:dart: Expose an application](how-to/expose.md) 20 | 21 | [:dart: Set up access policies for your application](../how-to/access-policies.md) 22 | 23 | [:dart: Communicate with another application](../how-to/communication.md) 24 | 25 | [:books: Complete application example](reference/application-example.md) 26 | 27 | [:books: Application specification](reference/application-spec.md) 28 | -------------------------------------------------------------------------------- /docs/workloads/application/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [application, how-to] 3 | --- 4 | 5 | # Create application 6 | 7 | This how-to guide will show you how to create a Nais manifest for your [application](../README.md). 8 | 9 | ## Setup 10 | 11 | Inside your application repository, create a `.nais`-folder. 12 | 13 | ```bash 14 | cd 15 | mkdir .nais 16 | ``` 17 | 18 | Create a file called `app.yaml` in the `.nais`-folder. 19 | 20 | ```bash 21 | touch .nais/app.yaml 22 | ``` 23 | 24 | ## Define your application 25 | 26 | Below is a basic example of an application manifest. 27 | 28 | Add the following content to the file, and insert the appropriate values in the placeholders on the highlighted lines: 29 | 30 | ???+ note ".nais/app.yaml" 31 | 32 | ```yaml hl_lines="5-7 9" 33 | apiVersion: nais.io/v1alpha1 34 | kind: Application 35 | metadata: 36 | name: 37 | namespace: 38 | spec: 39 | image: {{image}} # Placeholder variable to be replaced by the CI/CD pipeline 40 | port: 8080 41 | replicas: 42 | max: 4 43 | min: 2 44 | resources: 45 | requests: 46 | cpu: 200m 47 | memory: 128Mi 48 | ``` 49 | 50 | This application manifest represents a very basic daemon application. 51 | You will likely want to add more configuration to your application manifest based on your needs. 52 | 53 | ## Related pages 54 | 55 | :dart: [Build and deploy your application to Nais](../../../build/how-to/build-and-deploy.md). 56 | 57 | :dart: [Expose your application](./expose.md). 58 | 59 | :books: [Application spec reference](../reference/application-spec.md). 60 | 61 | :books: [Full Application example](../reference/application-example.md). 62 | 63 | :bulb: [Good practices for Nais workloads](../../explanations/good-practices.md). 64 | -------------------------------------------------------------------------------- /docs/workloads/application/how-to/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [application, how-to] 3 | --- 4 | 5 | # Delete your application 6 | 7 | ## Prerequisites 8 | 9 | - You're part of a [Nais team](../../../explanations/team.md) 10 | 11 | ## Delete your application 12 | 13 | 1. Open [Nais console :octicons-link-external-16:](https://console.<>.cloud.nais.io) in your browser 14 | 2. Select your team 15 | 3. Select the `Apps` tab 16 | 4. Select the application that you want to delete 17 | 5. Click the `Delete` button 18 | 19 | You will be prompted to confirm the deletion. 20 | If you have any resources connected to your application, these will also be listed. 21 | 22 | Once confirmed, the application will be permanently deleted. 23 | 24 | 6. Make sure that you also remove any related workflows and manifests in your Git repository. 25 | -------------------------------------------------------------------------------- /docs/workloads/application/how-to/expose.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [application, how-to, ingress] 3 | --- 4 | 5 | # Expose an application 6 | 7 | This guide will show you how to [expose your application](../explanations/expose.md) to end-users or applications in other environments by using an ingress. 8 | 9 | If your application only needs to be available to other applications running in the same environment, you should use [service discovery](../explanations/expose.md#service-discovery) instead. 10 | 11 | ## Select audience 12 | 13 | Select the correct audience from [the available domains in your environment](../../reference/environments.md). 14 | 15 | ## Define ingress 16 | 17 | Specify the desired hostname for your application in the application manifest with [`.spec.ingresses[]`](../reference/application-spec.md#ingresses): 18 | 19 | ```yaml hl_lines="4-5" title=".nais/app.yaml" 20 | apiVersion: nais.io/v1alpha1 21 | kind: Application 22 | spec: 23 | ingresses: 24 | - https://. 25 | ``` 26 | 27 | !!! warning "Subdomain restrictions" 28 | 29 | Subdomains must only contain lowercase letters, numbers, and hyphens. 30 | They may not start or end with a hyphen. 31 | 32 | Only one level of subdomains is allowed, e.g.: 33 | 34 | - `.` is allowed 35 | - `..` is not allowed 36 | 37 | ## Optional: Specify path for ingress 38 | 39 | An ingress may include a path to expose a subset of your application: 40 | 41 | ```yaml hl_lines="4-5" title=".nais/app.yaml" 42 | apiVersion: nais.io/v1alpha1 43 | kind: Application 44 | spec: 45 | ingresses: 46 | - https://./some-path 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/workloads/application/how-to/redirect.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [ application, how-to, redirect ] 3 | --- 4 | 5 | # Redirect a client 6 | 7 | To redirect traffic from one domain to another, you need to define an ingress `from` the old domain that redirects `to` the 8 | new domain, with [`.spec.redirects[]`](../reference/application-spec.md#redirects). 9 | 10 | The `redirects` field specifies URL redirects. It is structured as a mapping from a source URL to a target URL. 11 | 12 | A successful redirect will return a `302 Moved Temporarily` HTTP status code with location header set to the target URL. 13 | 14 | !!! info "Explicit redirect permission" 15 | The ingress being redirected has to have `nais.io/allow-redirect: true` set. 16 | This can be set as an annotation in the application spec. 17 | 18 | 19 | ??? note "Status code for redirects" 20 | The status code can not be overridden. 21 | 22 | ### Structure 23 | 24 | ```yaml hl_lines="4-5" title=".nais/app.yaml" 25 | apiVersion: nais.io/v1alpha1 26 | kind: Application 27 | spec: 28 | ingress: 29 | - https://. 30 | redirects: 31 | - from: https://. 32 | to: https://. 33 | ``` 34 | 35 | ### Parameters 36 | 37 | - **from**: *(string)* The source URL for the redirection. This is the URL that will be redirected. 38 | - **to**: *(string)* The target URL for the redirection. This is the URL that the client will be redirected to. 39 | 40 | ### Usage Example 41 | 42 | ```yaml hl_lines="4-5" title=".nais/app.yaml" 43 | apiVersion: nais.io/v1alpha1 44 | kind: Application 45 | spec: 46 | ingress: 47 | - http://example-new.nais.io 48 | redirects: 49 | - from: "http://example-old.nais.io" 50 | to: "http://example-new.nais.io" 51 | ``` 52 | 53 | ??? warning "Redirect restrictions" 54 | 55 | The `from` and `to` URLs must be valid URLs. 56 | The `to` URL must be a valid URL that is exposed by the application. 57 | 58 | In this example: 59 | 60 | - Requests to `http://example-old.nais.io` are redirected to `http://example-new.nais.io`. 61 | -------------------------------------------------------------------------------- /docs/workloads/explanations/environment.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, explanation] 3 | --- 4 | 5 | # The runtime environment 6 | 7 | Nais provides you with multiple _environments_ for you to run your [workloads](../README.md) in. 8 | Environments are sometimes also called _clusters_. 9 | 10 | :books: Find the full list of available environments in [the environment reference](../reference/environments.md). 11 | 12 | ## Namespaces 13 | 14 | For each environment, your [team](../../explanations/team.md) has its own _namespace_ separate from other teams. 15 | A namespace is a logical grouping of resources that are owned by your team. 16 | This is where you will deploy and run your workloads. 17 | 18 | The namespace and the resources within are only accessible to members of the owning team. 19 | 20 | ## Networking and Communication 21 | 22 | ### Zero trust 23 | 24 | By default, all workloads are isolated from each other and the outside world according to the _zero trust_ security model. 25 | This means that traffic to and from your workloads must be explicitly allowed. 26 | 27 | :bulb: [Learn more about zero trust](./zero-trust.md). 28 | 29 | ### Ingresses 30 | 31 | If you need to expose your workload to the outside world, you can do so by defining an _ingress_. 32 | 33 | Each environment provides you with a set of domains that you can use to expose your workloads to different audiences and networks. 34 | 35 | :bulb: [Learn more about ingresses](../application/explanations/expose.md#ingress). 36 | 37 | ### Service discovery 38 | 39 | If your workload needs to communicate with other workloads within the same environment, you can use _service discovery_. 40 | 41 | :bulb: [Learn more about service discovery](../application/explanations/expose.md#service-discovery). 42 | -------------------------------------------------------------------------------- /docs/workloads/explanations/imagerepository.md: -------------------------------------------------------------------------------- 1 | # Image repository 2 | 3 | Every team gets its own image repository where they push the images they run on Nais. 4 | 5 | When using the [nais/docker-build-push](https://github.com/nais/docker-build-push)-action in your workflow, this repository is used automatically. 6 | 7 | ## Image Restriction 8 | 9 | Nais restricts the use of images from other image registries for two main reasons. 10 | 11 | 1. We verify that the image has been uploaded either by an authorized Nais user or Github repository. 12 | 2. The provided repository uses [Image Streaming](https://cloud.google.com/kubernetes-engine/docs/how-to/image-streaming), ensuring consistently fast start-up times when auto-scaling or during platform maintenance. 13 | 14 | ## Using third-party images 15 | 16 | To use a third-party Docker image, you must upload it to your team’s repository. See the [Upload Third-Party Image](../how-to/upload-image.md) guide for instructions. 17 | -------------------------------------------------------------------------------- /docs/workloads/how-to/communication.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, how-to, service-discovery] 3 | --- 4 | 5 | # Communicate with other workloads 6 | 7 | This guide shows you how to communicate with other workloads inside the same environment or cluster via [_service discovery_](../application/explanations/expose.md#service-discovery). 8 | 9 | ## Prerequisites 10 | 11 | - Your workload has [configured policies for _outbound traffic_ to the target workload](access-policies.md#outbound-access) 12 | - The target workload has [configured policies for _inbound traffic_ from your workload](access-policies.md#inbound-access) 13 | 14 | ## Identify the target address 15 | 16 | To identity the address of the workload we are communicating with, we need to know its `name` and what `namespace` its running in. 17 | 18 | ### Target exists in the same namespace 19 | 20 | If the workload you are calling is in the same namespace, you can reach it by calling its name directly using HTTP like so: 21 | 22 | ```plaintext 23 | http:// 24 | ``` 25 | 26 | ### Target exists in another namespace 27 | 28 | If the workload is running in another team's namespace, you need to specify the namespace as well: 29 | 30 | ```plaintext 31 | http://. 32 | ``` 33 | 34 | {% if tenant() == "nav" %} 35 | 36 | !!! warning "Use full hostname when using webproxy on-premises" 37 | 38 | If your workload has [webproxy](../application/reference/application-spec.md#webproxy) enabled, you must use the full hostname for all service discovery calls: 39 | 40 | ```text 41 | http://..svc.nais.local 42 | ``` 43 | 44 | This is to ensure that your workload does not attempt to perform these in-cluster calls through the proxy, as the environment variable `NO_PROXY` includes `*.local`. 45 | 46 | {% endif %} 47 | 48 | ## Call the address 49 | 50 | Call the workload through its internal address using HTTP from your own workload: 51 | 52 | ```http 53 | GET /resource HTTP/1.1 54 | 55 | Host: . 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/workloads/how-to/disable-readonly.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, how-to] 3 | --- 4 | 5 | # Disable read-only file system 6 | 7 | This how-to shows how to disable read-only root file system in your workloads. 8 | 9 | !!! warning 10 | 11 | This setting helps protect your workloads from unauthorized writes. Only disable it if you are sure that your workload requires write access to the file system outside of `/tmp`. 12 | 13 | ## Add annotation to workload 14 | 15 | ```yaml title="nais.yaml" 16 | ... 17 | metadata: 18 | annotations: 19 | nais.io/read-only-file-system: "false" 20 | ``` 21 | 22 | Re-deploy your workload to apply the changes. 23 | 24 | !!! note 25 | 26 | Even with this setting enabled, you must ensure that the default user (`1069` or whatever you override it with) has write permission inside the Docker image. 27 | 28 | ## Related pages 29 | 30 | :books: [Container security](../reference/container-security.md) 31 | -------------------------------------------------------------------------------- /docs/workloads/how-to/override-user-group.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, how-to] 3 | --- 4 | 5 | # Overriding user and group that runs container process 6 | 7 | This how-to shows you how to override the default user and group (`1069`) that will run your container process. 8 | 9 | ## Add annotation to workload 10 | 11 | ```yaml title="nais.yaml" 12 | ... 13 | metadata: 14 | annotations: 15 | nais.io/run-as-user: "1001" 16 | nais.io/run-as-group: "1002" # defaults to same as run-as-user 17 | ``` 18 | 19 | Re-deploy your workload to apply the changes. 20 | 21 | ## Related pages 22 | 23 | :books: [Container security](../reference/container-security.md) 24 | -------------------------------------------------------------------------------- /docs/workloads/how-to/upload-image.md: -------------------------------------------------------------------------------- 1 | # Upload third-party image to image repository 2 | 3 | This how-to guide will show you how to upload a Docker image to your team's image repository. 4 | 5 | ## Prerequisites 6 | 7 | - [Nais CLI](../../operate/cli/how-to/install.md) installed. 8 | - A Docker runtime installed and running on your machine 9 | 10 | ## Log into Nais 11 | 12 | ```bash 13 | nais login 14 | ``` 15 | 16 | ## Register the Docker registry 17 | 18 | ```bash 19 | gcloud auth configure-docker europe-north1-docker.pkg.dev 20 | ``` 21 | 22 | ## Ensure you have the image locally 23 | 24 | Ensure the desired image is available on your machine by pulling it from its source or building it locally. For example: 25 | 26 | ```bash 27 | docker pull repository/my-image:tag --platform linux/amd64 28 | ``` 29 | 30 | !!! note "Specify the platform" 31 | Note that we are adding the `--platform linux/amd64` flag to ensure that the image we are pulling is compatible with the Nais platform. 32 | By default the architecture of the image will be the same as the host machine, which might not work. 33 | 34 | ## Locate the image repository URL 35 | 36 | Find the image repository URL on the settings page in the Nais console 37 | 38 | `https://console.<>.cloud.nais.io/team//settings` 39 | 40 | The URL will be on this format: 41 | 42 | `europe-north1-docker.pkg.dev/nais-management-/` 43 | 44 | ## Tag the image 45 | 46 | ```bash 47 | docker tag repository/my-image:tag europe-north1-docker.pkg.dev/nais-management-//my-image:tag 48 | ``` 49 | 50 | ## Push the image 51 | 52 | ```bash 53 | docker push europe-north1-docker.pkg.dev/nais-management-//my-image:tag 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /docs/workloads/job/.pages: -------------------------------------------------------------------------------- 1 | nav: 2 | - README.md 3 | - 🎯 How-To: how-to 4 | - 📚 Reference: reference 5 | - ... 6 | -------------------------------------------------------------------------------- /docs/workloads/job/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [job, explanation, workloads, services] 3 | --- 4 | 5 | # Nais job 6 | 7 | A Nais job is used for tasks meant to complete and then exit. This can either run as a one-off task or on a schedule, like a [cron job](https://en.wikipedia.org/wiki/Cron). 8 | 9 | A job is defined by its job manifest, which is a YAML file that describes how the job should be run and what resources it needs. 10 | 11 | Once the job manifest is applied, Nais will set up your job as specified. If you've requested resources, Nais will provision and configure your job to use those resources. 12 | 13 | ## Related pages 14 | 15 | [:dart: Create a job](how-to/create.md) 16 | 17 | [:dart: Set up access policies for your workload](../how-to/access-policies.md) 18 | 19 | [:dart: Communicate with another workload](../how-to/communication.md) 20 | 21 | [:books: Complete job example](reference/naisjob-example.md) 22 | 23 | [:books: Job specification](reference/naisjob-spec.md) 24 | -------------------------------------------------------------------------------- /docs/workloads/job/how-to/create.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [job, how-to] 3 | --- 4 | 5 | # Create job 6 | 7 | This how-to guide will show you how to create a Nais manifest for your [job](../README.md). 8 | 9 | ## Setup 10 | 11 | Inside your job repository, create a `.nais`-folder. 12 | 13 | ```bash 14 | cd 15 | mkdir .nais 16 | ``` 17 | 18 | Create a file called `job.yaml` in the `.nais`-folder. 19 | 20 | ```bash 21 | touch .nais/job.yaml 22 | ``` 23 | 24 | ## Define your job 25 | 26 | Below is a basic example of an job manifest. 27 | 28 | Add the following content to the file, and insert the appropriate values in the placeholders on the highlighted lines: 29 | 30 | ???+ note ".nais/app.yaml" 31 | 32 | ```yaml hl_lines="5-7 9" 33 | apiVersion: nais.io/v1 34 | kind: Naisjob 35 | metadata: 36 | labels: 37 | team: 38 | name: 39 | namespace: 40 | spec: 41 | schedule: "0 * * * *" # Runs every hour 42 | image: {{image}} # Placeholder variable to be replaced by the CI/CD pipeline 43 | resources: 44 | requests: 45 | cpu: 200m 46 | memory: 128Mi 47 | ``` 48 | 49 | This job manifest will run your code every hour. If you want to run your job only once, you can remove the `schedule` field. 50 | 51 | ## Related pages 52 | 53 | :dart: [Build and deploy your job to Nais](../../../build/how-to/build-and-deploy.md). 54 | 55 | :books: [Job spec reference](../reference/naisjob-spec.md). 56 | 57 | :books: [Complete job example](../reference/naisjob-example.md). 58 | -------------------------------------------------------------------------------- /docs/workloads/job/how-to/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [job, how-to] 3 | --- 4 | 5 | # Delete your job 6 | 7 | ## Prerequisites 8 | 9 | - You're part of a [Nais team](../../../explanations/team.md) 10 | 11 | ## Delete your job 12 | 13 | 1. Open [Nais console :octicons-link-external-16:](https://console.<>.cloud.nais.io) in your browser 14 | 2. Select your team 15 | 3. Select the `Job` tab 16 | 4. Select the job that you want to delete 17 | 5. Click the `Delete` button 18 | 19 | You will be prompted to confirm the deletion. 20 | If you have any resources connected to your job, these will also be listed. 21 | 22 | Once confirmed, the job will be permanently deleted. 23 | 24 | 6. Make sure that you also remove any related workflows and manifests in your Git repository. 25 | -------------------------------------------------------------------------------- /docs/workloads/reference/access-policies.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, reference] 3 | --- 4 | 5 | # Access policy reference 6 | 7 | ## Default allowed external hosts 8 | 9 | The following hosts are by default accessible for every workload: 10 | 11 | | Host / service | Port | Protocol | 12 | |-----------------------------|------|-----------| 13 | | `kube-dns` | 53 | UDP / TCP | 14 | | `metadata.google.internal` | 80 | TCP | 15 | | `private.googleapis.com` | 443 | TCP | 16 | | `login.microsoftonline.com` | 443 | TCP | 17 | | `graph.microsoft.com` | 443 | TCP | 18 | | `aivencloud.com` | 443 | TCP | 19 | 20 | You do not need to specify these hosts in your access policies. 21 | 22 | ## Advanced: Access Kubernetes API 23 | 24 | Kubernetes offers an API to query or manipulate the state of its objects. 25 | For details about the Kubernetes API, see the [official documentation](https://kubernetes.io/docs/concepts/overview/kubernetes-api/). 26 | 27 | !!! danger "Here be dragons!" 28 | 29 | Usage of the Kubernetes API from workloads is done at your own risk. 30 | This is an advanced use case that most workloads should not need. 31 | 32 | Nais does not offer any uptime, stability or compatibility guarantees for the API. 33 | 34 | If you're considering using the Kubernetes API, we recommend that you first reach out to the Nais team for guidance. 35 | 36 | To allow outbound network access from your workload to the Kubernetes API server, you must explicitly add a label to your workload manifest: 37 | 38 | ```yaml title="app.yaml" hl_lines="7" 39 | apiVersion: "nais.io/v1alpha1" 40 | kind: "Application" 41 | metadata: 42 | name: my-app 43 | namespace: my-team 44 | labels: 45 | apiserver-access: "enabled" 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/workloads/reference/container-security.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, reference] 3 | --- 4 | 5 | # Container security 6 | 7 | The following settings are applied to all containers running in Nais: 8 | 9 | - Read only root filesystem. Only `/tmp` is writable. 10 | - Runs as non-root, with user and group id `1069` 11 | 12 | To override these settings, see the following how-to guides: 13 | 14 | :dart: [Disable read-only file system](../how-to/disable-readonly.md) 15 | 16 | :dart: [Overriding runAsUser / runAsGroup](../how-to/override-user-group.md) 17 | -------------------------------------------------------------------------------- /docs/workloads/reference/default-variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, reference] 3 | --- 4 | 5 | # Default workload variables 6 | 7 | These environment variables will be injected into your workload container 8 | 9 | | variable | example | source | 10 | |:--------------------|:-------------------------|:-------------------------------------------------| 11 | | `PORT` | `8080` | defaults to 8080, otherwise `.spec.port` | 12 | | `BIND_ADDRESS` | `0.0.0.0:8080` | 0.0.0.0: (see above) | 13 | | `NAIS_APP_NAME` | `myapp` | metadata.name from app.yaml | 14 | | `NAIS_NAMESPACE` | `default` | metadata.namespace from app.yaml | 15 | | `NAIS_APP_IMAGE` | `navikt/myapp:69` | spec.image from app.yaml | 16 | | `NAIS_CLUSTER_NAME` | `prod` | which environment you are running in | 17 | | `NAIS_CLIENT_ID` | `prod-fss:default:myapp` | concatenation of cluster, namespace and app name | 18 | | `NAIS_POD_NAME` | `myapp-74dbb9ff9f-7zvsh` | the pod's name | 19 | -------------------------------------------------------------------------------- /docs/workloads/reference/webproxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: [workloads, reference, webproxy] 3 | conditional: [tenant, nav] 4 | --- 5 | 6 | # Webproxy 7 | 8 | In Navs on-premises environments, workloads that need to make external HTTP(S) requests must set `webproxy` to `true` in their [application spec](../../workloads/application/reference/application-spec.md#webproxy). 9 | 10 | When `webproxy` is enabled, the platform provides a set of environment variables to configure the proxy settings for your workload. 11 | 12 | ## Linux 13 | Most Linux applications should auto-detect these settings from the `$HTTP_PROXY`, `$HTTPS_PROXY` and `$NO_PROXY` environment variables (and their lowercase counterparts). 14 | 15 | ## Java 16 | 17 | Java applications can start the JVM using parameters from the `$JAVA_PROXY_OPTIONS` environment variable. 18 | To do this, you either need a launcher script that copies the value from `JAVA_PROXY_OPTIONS` to `JDK_JAVA_OPTIONS`, 19 | or you can set the `JDK_JAVA_OPTIONS` environment variable directly in your [application spec](../application/reference/application-spec.md#env).: 20 | 21 | ``` 22 | env: 23 | - name: JDK_JAVA_OPTIONS 24 | value: $(JAVA_PROXY_OPTIONS) 25 | ``` 26 | 27 | This takes advantage of [Kubernetes Dependent Environment Variables](https://kubernetes.io/docs/tasks/inject-data-application/define-interdependent-environment-variables/), which allows you to use the value of one environment variable in another. 28 | 29 | Since environment variables set by the platform are defined before the application variables, you can refer to the `JAVA_PROXY_OPTIONS` variable when setting `JDK_JAVA_OPTIONS`. 30 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1737376395, 6 | "narHash": "sha256-gqJM6ELmoy7IOULIDx5GkdWvUnHlNyRmgJqPZOzM/7Y=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "f5b5e4d69cb858b79bfbc300980b13b4218d5b01", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "repo": "nixpkgs", 15 | "type": "github" 16 | } 17 | }, 18 | "root": { 19 | "inputs": { 20 | "nixpkgs": "nixpkgs" 21 | } 22 | } 23 | }, 24 | "root": "root", 25 | "version": 7 26 | } 27 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "dev env for docs"; 3 | 4 | # Flake inputs 5 | inputs = { 6 | nixpkgs.url = "github:NixOS/nixpkgs"; # also valid: "nixpkgs" 7 | }; 8 | 9 | # Flake outputs 10 | outputs = { self, nixpkgs }: 11 | let 12 | # Systems supported 13 | allSystems = [ 14 | "x86_64-linux" # 64-bit Intel/AMD Linux 15 | "aarch64-linux" # 64-bit ARM Linux 16 | "x86_64-darwin" # 64-bit Intel macOS 17 | "aarch64-darwin" # 64-bit ARM macOS 18 | ]; 19 | 20 | # Helper to provide system-specific attributes 21 | forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { 22 | pkgs = import nixpkgs { inherit system; }; 23 | }); 24 | in 25 | { 26 | # Development environment output 27 | devShells = forAllSystems ({ pkgs }: { 28 | default = 29 | pkgs.mkShell { 30 | packages = with pkgs; [ 31 | python311 32 | poetry 33 | ]; 34 | }; 35 | }); 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import textwrap 3 | 4 | 5 | def define_env(env): 6 | @env.macro 7 | def tenant(): 8 | return os.getenv('TENANT', 'tenant') 9 | 10 | @env.macro 11 | def tenant_url(app: str, path: str = ''): 12 | if tenant() == 'nav' and app == 'cdn': 13 | return f'https://cdn.nav.no/{path}' 14 | 15 | return f'https://{app}.{tenant()}.cloud.nais.io/{path}' 16 | 17 | @env.macro 18 | def gcp_only(feature: str): 19 | if tenant() == "nav": 20 | return textwrap.dedent(f"""\ 21 | !!! gcp-only "{feature} is only available in GCP" 22 | 23 | {feature} is only available in GCP clusters, and will not work in on-prem clusters. 24 | """) 25 | return "" 26 | 27 | @env.macro 28 | def naisdevice_name(): 29 | if tenant() == "nav": 30 | return "naisdevice" 31 | 32 | return "naisdevice-tenant" 33 | 34 | @env.macro 35 | def not_in_test_nais(feature: str): 36 | if tenant() == "test-nais": 37 | return textwrap.dedent(f"""\ 38 | !!! not-in-test-nais "{feature} is not available in test-nais clusters" 39 | 40 | {feature} is not available in test-nais clusters. 41 | """) 42 | return "" 43 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "doc" 3 | version = "0.1.0" 4 | description = "nais developer documentation" 5 | authors = [] 6 | package-mode = false 7 | requires-poetry = ">=2.0" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.11" 11 | mkdocs = "^1.5.3" 12 | Pygments = "^2.18.0" 13 | pymdown-extensions = "^10.15" 14 | mkdocs-material = "^9.6.14" 15 | mkdocs-git-revision-date-localized-plugin = "^1.4.7" 16 | mkdocs-redirects = "^1.2.2" 17 | mkdocs-git-committers-plugin-2 = "^2.5.0" 18 | mkdocs-macros-plugin = "^1.3.7" 19 | mkdocs-awesome-pages-plugin = "^2.9.3" 20 | mkdocs-file-filter-plugin = "^0.2.0" 21 | 22 | [build-system] 23 | requires = ["poetry-core>=1.0.0"] 24 | build-backend = "poetry.core.masonry.api" 25 | --------------------------------------------------------------------------------