Skip to content
Branch: master
Find file History


This section will take you through the deployment of your application, using the NAIS deploy tool.

NAIS deploy enables you to deploy your application into any cluster from any continuous integration platform, including CircleCI, Travis CI, and Jenkins.

Note: Using naisd or JIRA Autodeploy to deploy your application? These mechanisms are deprecated and are going to be shut down. See migration guide from naisd to Naiserator. All information on the current page relates to Naiserator compatible nais.yaml files. You can also read the naisd user documentation.

How it works

  1. In your CircleCI/Jenkins build pipeline, create a deployment request using deployment-cli. This request is sent to Github's deployment API and is forwarded to NAIS deploy.
  2. NAIS deploy verifies the integrity and authenticity of the deployment, assumes the identity of the deploying team, and applies your Kubernetes resources into the specified cluster.
  3. If you deployed any Application or Deployment resources, NAIS deploy will wait until these are rolled out successfully, or a timeout occurs.
  4. The deployment status is continually posted back to Github and is available through their API, enabling integration with your pipeline or monitoring setup.

Getting started

  1. Make sure the prerequisites are met before attempting to use NAIS deploy.
  2. Enable deployments for your repository.
  3. Obtain Github deployment credentials.
  4. Implement NAIS deploy in your pipeline.
  5. When things break, check the section on troubleshooting.


  • Create a nais.yaml file for any application you want to deploy. A nais.yaml file contains an Application resource. The application resource provides NAIS with the necessary information to run your application. If starting out for the first time, try the nais.yaml minimal example.

  • The repository containing nais.yaml must be on Github.

  • Secure your Github repository by restricting write access to team members. Activating NAIS deploy for your repository will enable anyone with write access to your repository to deploy on behalf of your team. This is a major security concern and should not be overlooked.

  • Be a maintainer of a Github team. The team name must be the same as your Kubernetes team label, and additionally must have write access to your repository.

Enable deployments for your repository

NAIS deploy must authorize your Github repository before you can perform deployments. This must be done once per repository. When authorizing, you can pick one or more teams to deploy as. Any permissions these teams have in the NAIS cluster will be granted to the deployment pipeline. In order to do this, you need to have maintainer access rights to your Github team, and admin access to the repository.

When you're ready, go to the registration portal and follow the instructions.

Best practice: use a single repository for all your team's infrastructure code and nais.yaml files.

Obtain Github deployment credentials

The self-service way of obtaining credentials is to create a personal access token that your CI pipeline can use to trigger the deployment. The token needs only the scope repo_deployment.

It is possible to authenticate as a Github App as well. The drawback is that you need to be a Github admin. Usage and implementation of this method is left as an exercise to the reader.

Performing the deployment

At this point, you have:

  • met the prerequisites
  • enabled deployments
  • obtained credentials

You are ready to perform a deployment.

Using CircleCI

If using CircleCI (recommended) then you can use the nais-deployment Orb to set up your deployment with close to zero configuration.

In a nutshell, you create a .circleci/config.yml file in your repository with the contents below. Sensitive data such as keys or passwords must go into environment variables, configured in the CircleCI user interface.

version: 2.1
  nais: 'navikt/nais-deployment@1.4.0'
      - nais/deploy:
          context: NAIS deployment     # gives you $DOCKER_LOGIN and $DOCKER_PASSWORD
          repo: navikt/example-repo
          image: navikt/example-image
          github-app-id: 1337          # when authenticating as a Github application
          nais-template: nais.yaml
          environment: dev-fss
          team: awesome-team           # needs to be identical in Kubernetes and Github
          enable-vars: true            # set to true to enable templating support
          template-vars: dev-fss.json  # file with template variables

Travis CI, Jenkins, or manually using CircleCI

In your pipeline, use our internal tool deployment-cli to make deployment requests. Variables you need include environment, repository, team, application version, Kubernetes resources, and your Github credentials.

Example syntax:

deployment-cli create \
  --cluster=dev-fss \
  --repository=navikt/deployment \
  --team=<TEAM> \
  --version=<APP VERSION> \
  --appid=1234 \
  --key=/path/to/private-key.pem \
  --resources=nais.yaml \

Once you are ready to advance from development to production, please read the deployment-cli templating guide.


Your deployment status page can be found on Github, under the repository you are deploying from. The status page will live at the URL<YOUR_REPOSITORY>/deployments. Links to deployment logs are available from this page.

Generally speaking, if the deployment status is anything else than success, queued, or pending, it means that your deployment failed. Check the logs and compare messages to the table below before asking for support.

If everything fails, and you checked your logs, you can ask for help in the #nais-deployment channel on Slack.

Message Action
the repository 'foo/bar' does not have access to deploy as team 'Baz' Is your team name in lowercase everywhere?
Repository foo/bar is not registered Please read the registering your repository section.
Deployment status error There is an error with your request. The reason should be specified in the error message.
Deployment status failure Your application didn't pass its health checks during the 5 minute startup window. It is probably stuck in a crash loop due to mis-configuration. Check your application logs using kubectl logs <POD> and event logs using kubectl describe app <APP>
Deployment is stuck at queued The deployment hasn't been picked up by the worker process. Did you specify a supported cluster with --cluster=<CLUSTER>?
team foo does not exist in Azure AD Your team is not registered in the team portal.

If for any reason you are unable to use deployment-cli, please read the section on NAIS deploy with cURL.

Advanced usage

Supported clusters

Please use one of the following clusters. The usage of preprod-*** is not supported.

  • dev-fss
  • dev-sbs
  • prod-fss
  • prod-sbs

NAIS deploy with cURL

A deployment into the Kubernetes clusters starts with a POST request to the GitHub Deployment API. The request contains information about which cluster to deploy to, which team to deploy as, and what resources should be applied.

Example request:

    "ref": "master",
    "description": "Automated deployment request from our pretty pipeline",
    "environment": "prod-sbs",
    "payload": {
        "version": [1, 0, 0],
        "team": "github-team-name",
        "kubernetes": {
            "resources": [
                { kind: "Application", apiVersion: "", metadata: {...}, spec: {...} },
                { kind: "ConfigMap", apiVersion: "v1", metadata: {...}, spec: {...} },

The data can be posted from standard input through curl using a command similar to:

curl \
    -X POST \
    -d@- \
    -H "Accept: application/vnd.github.ant-man-preview+json" \
    -u <USERNAME>:<TOKEN> \<REPOSITORY_NAME>/deployments

The version in the payload should be set to [1, 0, 0].

This version field have nothing to do with your application version. It is used internally by the deployment orchestrator to keep things stable and roll out new features gracefully.

Changes will be rolled out using semantic versioning.

Deployment request spec

Key Description Version added
environment Which environment to deploy to. N/A
payload.version This is the payload API version, as described below. Array of three digits, denoting major, minor, and patch level version. 1.0.0 Github team name, used as credentials for deploying into the Kubernetes cluster. 1.0.0
payload.kubernetes.resources List of Kubernetes resources that should be applied into the cluster. Your nais.yaml file goes here, in JSON format instead of YAML. 1.0.0

Manual deploy with a human involved

Performing deployments manually requires that you have access to the cluster and kubectl configured.

$ kubectl apply -f nais.yaml<app name> created 

Verify that your application is running

$ kubectl get pod -l app=<myapp>
NAME                          READY   STATUS    RESTARTS   AGE
<app name>-59cbd7c89c-8h6wp   1/1     Running   0          4s
<app name>-59cbd7c89c-xpshz   1/1     Running   0          5s

You can also check that the Application resource was successfully created

$ kubectl describe app <my app>
  Type    Reason       Age        From        Message
  ----    ------       ----       ----        -------
  Normal  synchronize  3s         naiserator  successfully synchronized application resources (hash = 13485216922060251669)
You can’t perform that action at this time.