One place for hosting & domains


      Webinar Series: Kubernetes Package Management with Helm and CI/CD with Jenkins X

      Webinar Series

      This article supplements a webinar series on doing CI/CD with Kubernetes. The series discusses how to take a cloud native approach to building, testing, and deploying applications, covering release management, cloud native tools, service meshes, and CI/CD tools that can be used with Kubernetes. It is designed to help developers and businesses that are interested in integrating CI/CD best practices with Kubernetes into their workflows.

      This tutorial includes the concepts and commands from the second session of the series, Kubernetes Package Management with Helm and CI/CD with Jenkins X.

      Warning: The procedures in this tutorial are meant for demonstration purposes only. As a result, they don’t follow the best practices and security measures necessary for a production-ready deployment.


      In order to reduce error and organize complexity when deploying an application, CI/CD systems must include robust tooling for package management/deployment and pipelines with automated testing. But in modern production environments, the increased complexity of cloud-based infrastructure can present problems for putting together a reliable CI/CD environment. Two Kubernetes-specific tools developed to solve this problem are the Helm package manager and the Jenkins X pipeline automation tool.

      Helm is a package manager specifically designed for Kubernetes, maintained by the Cloud Native Computing Foundation (CNCF) in collaboration with Microsoft, Google, Bitnami, and the Helm contributor community. At a high level, it accomplishes the same goals as Linux system package managers like APT or YUM: managing the installation of applications and dependencies behind the scenes and hiding the complexity from the user. But with Kubernetes, the need for this kind of management is even more pronounced: Installing applications requires the complex and tedious orchestration of YAML files, and upgrading or rolling back releases can be anywhere from difficult to impossible. In order to solve this problem, Helm runs on top of Kubernetes and packages applications into pre-configured resources called charts, which the user can manage with simple commands, making the process of sharing and managing applications more user-friendly.

      Jenkins X is a CI/CD tool used to automate production pipelines and environments for Kubernetes. Using Docker images, Helm charts, and the Jenkins pipeline engine, Jenkins X can automatically manage releases and versions and promote applications between environments on GitHub.

      In this second article of the CI/CD with Kubernetes series, you will preview these two tools by:

      • Managing, creating, and deploying Kubernetes packages with Helm.

      • Building a CI/CD pipeline with Jenkins X.

      Though a variety of Kubernetes platforms can use Helm and Jenkins X, in this tutorial you will run a simulated Kubernetes cluster, set up in your local environment. To do this, you will use Minikube, a program that allows you to try out Kubernetes tools on your own machine without having to set up a true Kubernetes cluster.

      By the end of this tutorial, you will have a basic understanding of how these Kubernetes-native tools can help you implement a CI/CD system for your cloud application.


      To follow this tutorial, you will need:

      • An Ubuntu 16.04 server with 16 GB of RAM or above. Since this tutorial is meant for demonstration purposes only, commands are run from the root account. Note that the unrestrained privileges of this account do not adhere to production-ready best practices and could affect your system. For this reason, it is suggested to follow these steps in a test environment such as a virtual machine or a DigitalOcean Droplet.

      • A GitHub account and GitHub API token. Be sure to record this API token so that you can enter it during the Jenkins X portion of this tutorial.

      • Familiarity with Kubernetes concepts. Please refer to the article An Introduction to Kubernetes for more details.

      Step 1 — Creating a Local Kubernetes Cluster with Minikube

      Before setting up Minikube, you will have to install its dependencies, including the Kubernetes command line tool kubectl, the bidirectional data transfer relay socat, and the container program Docker.

      First, make sure that your system’s package manager can access packages over HTTPS with apt-transport-https:

      • apt-get update
      • apt-get install apt-transport-https

      Next, in order to ensure the kubectl download is valid, add the GPG key for the official Google repository to your system:

      • curl -s | apt-key add -

      Once you have added the GPG key, create the file /etc/apt/sources.list.d/kubernetes.list by opening it in your text editor:

      • nano /etc/apt/sources.list.d/kubernetes.list

      Once this file is open, add the following line:


      deb kubernetes-xenial main

      This will show your system the source for downloading kubectl. Once you have added the line, save and exit the file. With the nano text editor, you can do this by pressing CTRL+X, typing y, and pressing ENTER.

      Finally, update the source list for APT and install kubectl, socat, and

      • apt-get update
      • apt-get install -y kubectl socat

      Note: For Minikube to simulate a Kubernetes cluster, you must download the package rather than the newer docker-ce release. For production-ready environments, docker-ce would be the more appropriate choice, since it is better maintained in the official Docker repository.

      Now that you have installed kubectl, you can proceed with installing Minikube. First, use curl to download the program’s binary:

      • curl -Lo minikube

      Next, change the access permissions of the file you just downloaded so that your system can execute it:

      Finally, copy the minikube file to the executable path at /usr/local/bin/ and remove the original file from your home directory:

      • cp minikube /usr/local/bin/
      • rm minikube

      With Minikube installed on your machine, you can now start the program. To create a Minikube Kubernetes cluster, use the following command:

      • minikube start --vm-driver none

      The flag --vm-driver none instructs Minikube to run Kubernetes on the local host using containers rather than a virtual machine. Running Minikube this way means that you do not need to download a VM driver, but also means that the Kubernetes API server will run insecurely as root.

      Warning: Because the API server with root privileges will have unlimited access to the local host, it is not recommended to run Minikube using the none driver on personal workstations.

      Now that you have started Minikube, check to make sure that your cluster is running with the following command:

      You will receive the following output, with your IP address in place of your_IP_address:

      minikube: Running
      cluster: Running
      kubectl: Correctly Configured: pointing to minikube-vm at your_IP_address

      Now that you have set up your simulated Kubernetes cluster using Minikube, you can gain experience with Kubernetes package management by installing and configuring the Helm package manager on top of your cluster.

      Step 2 — Setting Up the Helm Package Manager on your Cluster

      In order to coordinate the installation of applications on your Kubernetes cluster, you will now install the Helm package manager. Helm consists of a helm client that runs outside the cluster and a tiller server that manages application releases from within the cluster. You will have to install and configure both to successfully run Helm on your cluster.

      To install the Helm binaries, first use curl to download the following installation script from the official Helm GitHub repository into a new file named

      • curl >

      Since this script requires root access, change the permission of so that the owner of the file (in this case, root) can read, write, and execute it:

      Now, execute the script:

      When the script finishes, you will have helm installed to /usr/local/bin/helm and tiller installed to /usr/local/bin/tiller.

      Though tiller is now installed, it does not yet have the correct roles and permissions to access the necessary resources in your Kubernetes cluster. To assign these roles and permissions to tiller, you will have to create a service account named tiller. In Kubernetes, a service account represents an identity for processes that run in a pod. After a process is authenticated through a service account, it can then contact the API server and access cluster resources. If a pod is not assigned a specific service account, it gets the default service account. You will also have to create a Role-Based access control (RBAC) rule that authorizes the tiller service account.

      In Kubernetes RBAC API, a role contains rules that determine a set of permissions. A role can be defined with a scope of namespace or cluster, and can only grant access to resources within a single namespace. ClusterRole can create the same permissions on the level of a cluster, granting access to cluster-scoped resources like nodes and namespaced resources like pods. To assign the tiller service account the right role, create a YAML file called rbac_helm.yaml and open it in your text editor:

      Add the following lines to the file to configure the tiller service account:


      apiVersion: v1
      kind: ServiceAccount
        name: tiller
        namespace: kube-system
      kind: ClusterRoleBinding
        name: tiller
        kind: ClusterRole
        name: cluster-admin
        - kind: ServiceAccount
          name: tiller
          namespace: kube-system
        - kind: User
          name: "admin"
        - kind: User
          name: "kubelet"
        - kind: Group
          name: system:serviceaccounts

      In the preceding file, ServiceAccount allows the tiller processes to access the apiserver as an authenticated service account. ClusterRole grants certain permissions to a role, and ClusterRoleBinding assigns that role to a list of subjects, including the tiller service account, the admin and kubelet users, and the system:serviceaccounts group.

      Next, deploy the configuration in rbac_helm.yaml with the following command:

      • kubectl apply -f rbac_helm.yaml

      With the tiller configuration deployed, you can now initialize Helm with the --service-acount flag to use the service account you just set up:

      • helm init --service-account tiller

      You will receive the following output, representing a successful initialization:


      Creating /root/.helm Creating /root/.helm/repository Creating /root/.helm/repository/cache Creating /root/.helm/repository/local Creating /root/.helm/plugins Creating /root/.helm/starters Creating /root/.helm/cache/archive Creating /root/.helm/repository/repositories.yaml Adding stable repo with URL: Adding local repo with URL: $HELM_HOME has been configured at /root/.helm. Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster. Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy. To prevent this, run `helm init` with the --tiller-tls-verify flag. For more information on securing your installation see: Happy Helming!

      This creates a tiller pod in the kube-system namespace. It also creates the .helm default repository in your $HOME directory and configures the default Helm stable chart repository at and the local Helm repository at

      To make sure that the tiller pod is running in the kube-system namespace, enter the following command:

      • kubectl --namespace kube-system get pods

      In your list of pods, tiller-deploy will appear, as is shown in the following output:


      NAME READY STATUS RESTARTS AGE etcd-minikube 1/1 Running 0 2h kube-addon-manager-minikube 1/1 Running 0 2h kube-apiserver-minikube 1/1 Running 0 2h kube-controller-manager-minikube 1/1 Running 0 2h kube-dns-86f4d74b45-rjql8 3/3 Running 0 2h kube-proxy-dv268 1/1 Running 0 2h kube-scheduler-minikube 1/1 Running 0 2h kubernetes-dashboard-5498ccf677-wktkl 1/1 Running 0 2h storage-provisioner 1/1 Running 0 2h tiller-deploy-689d79895f-bggbk 1/1 Running 0 5m

      If the tiller pod's status is Running, it can now manage Kubernetes applications from inside your cluster on behalf of Helm.

      To make sure that the entire Helm application is working, search the Helm package repositiories for an application like MongoDB:

      In the output, you will see a list of possible applications that fit your search term:


      NAME CHART VERSION APP VERSION DESCRIPTION stable/mongodb 5.4.0 4.0.6 NoSQL document-oriented database that stores JSON-like do... stable/mongodb-replicaset 3.9.0 3.6 NoSQL document-oriented database that stores JSON-like do... stable/prometheus-mongodb-exporter 1.0.0 v0.6.1 A Prometheus exporter for MongoDB metrics stable/unifi 0.3.1 5.9.29 Ubiquiti Network's Unifi Controller

      Now that you have installed Helm on your Kubernetes cluster, you can learn more about the package manager by creating a sample Helm chart and deploying an application from it.

      Step 3 — Creating a Chart and Deploying an Application with Helm

      In the Helm package manager, individual packages are called charts. Within a chart, a set of files defines an application, which can vary in complexity from a pod to a structured, full-stack app. You can download charts from the Helm repositories, or you can use the helm create command to create your own.

      To test out the capabilities of Helm, create a new Helm chart named demo with the following command:

      In your home directory, you will find a new directory called demo, within which you can create and edit your own chart templates.

      Move into the demo directory and use ls to list its contents:

      You will find the following files and directories in demo:


      charts  Chart.yaml  templates  values.yaml

      Using your text editor, open up the Chart.yaml file:

      Inside, you will find the following contents:


      apiVersion: v1
      appVersion: "1.0"
      description: A Helm chart for Kubernetes
      name: demo
      version: 0.1.0

      In this Chart.yaml file, you will find fields like apiVersion, which must be always v1, a description that gives additional information about what demo is, the name of the chart, and the version number, which Helm uses as a release marker. When you are done examining the file, close out of your text editor.

      Next, open up the values.yaml file:

      In this file, you will find the following contents:


      # Default values for demo.
      # This is a YAML-formatted file.
      # Declare variables to be passed into your templates.
      replicaCount: 1
        repository: nginx
        tag: stable
        pullPolicy: IfNotPresent
      nameOverride: ""
      fullnameOverride: ""
        type: ClusterIP
        port: 80
        enabled: false
        annotations: {}
          # nginx
          # "true"
        paths: []
          - chart-example.local
        tls: []
        #  - secretName: chart-example-tls
        #    hosts:
        #      - chart-example.local
      resources: {}
        # We usually recommend not to specify default resources and to leave this as a conscious
        # choice for the user. This also increases chances charts run on environments with little
        # resources, such as Minikube. If you do want to specify resources, uncomment the following
        # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
        # limits:
        #  cpu: 100m
        #  memory: 128Mi
        # requests:
        #  cpu: 100m
        #  memory: 128Mi
      nodeSelector: {}
      tolerations: []
      affinity: {}

      By changing the contents of values.yaml, chart developers can supply default values for the application defined in the chart, controlling replica count, image base, ingress access, secret management, and more. Chart users can supply their own values for these parameters with a custom YAML file using helm install. When a user provides custom values, these values will override the values in the chart’s values.yaml file.

      Close out the values.yaml file and list the contents of the templates directory with the following command:

      Here you will find templates for various files that can control different aspects of your chart:


      deployment.yaml  _helpers.tpl  ingress.yaml  NOTES.txt  service.yaml  tests

      Now that you have explored the demo chart, you can experiment with Helm chart installation by installing demo. Return to your home directory with the following command:

      Install the demo Helm chart under the name web with helm install:

      • helm install --name web ./demo

      You will get the following output:


      NAME: web LAST DEPLOYED: Wed Feb 20 20:59:48 2019 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web-demo ClusterIP <none> 80/TCP 0s ==> v1/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE web-demo 1 0 0 0 0s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE web-demo-5758d98fdd-x4mjs 0/1 ContainerCreating 0 0s NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace default -l "," -o jsonpath="{.items[0]}") echo "Visit to use your application" kubectl port-forward $POD_NAME 8080:80

      In this output, you will find the STATUS of your application, plus a list of relevant resources in your cluster.

      Next, list the deployments created by the demo Helm chart with the following command:

      This will yield output that will list your active deployments:



      Listing your pods with the command kubectl get pods would show the pods that are running your web application, which would look like the following:


      NAME READY STATUS RESTARTS AGE web-demo-5758d98fdd-nbkqd 1/1 Running 0 4m

      To demonstrate how changes in the Helm chart can release different versions of your application, open up demo/values.yaml in your text editor and change replicaCount: to 3 and image:tag: from stable to latest. In the following code block, you will find what the YAML file should look like after you have finished modifying it, with the changes highlighted:


      # Default values for demo.
      # This is a YAML-formatted file.
      # Declare variables to be passed into your templates.
      replicaCount: 3
        repository: nginx
        tag: latest
        pullPolicy: IfNotPresent
      nameOverride: ""
      fullnameOverride: ""
        type: ClusterIP
        port: 80
      . . .

      Save and exit the file.

      Before you deploy this new version of your web application, list your Helm releases as they are now with the following command:

      You will receive the following output, with the one deployment you created earlier:


      NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE web 1 Wed Feb 20 20:59:48 2019 DEPLOYED demo-0.1.0 1.0 default

      Notice that REVISION is listed as 1, indicating that this is the first revision of the web application.

      To deploy the web application with the latest changes made to demo/values.yaml, upgrade the application with the following command:

      Now, list the Helm releases again:

      You will receive the following output:


      NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE web 2 Wed Feb 20 21:18:12 2019 DEPLOYED demo-0.1.0 1.0 default

      Notice that REVISION has changed to 2, indicating that this is the second revision.

      To find the history of the Helm releases for web, use the following:

      This will show both of the revisions of the web application:


      REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
      1               Wed Feb 20 20:59:48 2019        SUPERSEDED      demo-0.1.0      Install complete
      2               Wed Feb 20 21:18:12 2019        DEPLOYED        demo-0.1.0      Upgrade complete

      To roll back your application to revision 1, enter the following command:

      This will yield the following output:


      Rollback was a success! Happy Helming!

      Now, bring up the Helm release history:

      You will receive the following list:


      REVISION UPDATED STATUS CHART DESCRIPTION 1 Wed Feb 20 20:59:48 2019 SUPERSEDED demo-0.1.0 Install complete 2 Wed Feb 20 21:18:12 2019 SUPERSEDED demo-0.1.0 Upgrade complete 3 Wed Feb 20 21:28:48 2019 DEPLOYED demo-0.1.0 Rollback to 1

      By rolling back the web application, you have created a third revision that has the same settings as revision 1. Remember, you can always tell which revision is active by finding the DEPLOYED item under STATUS.

      To prepare for the next section, clean up your testing area by deleting your web release with the helm delete command:

      Examine the Helm release history again:

      You will receive the following output:


      REVISION UPDATED STATUS CHART DESCRIPTION 1 Wed Feb 20 20:59:48 2019 SUPERSEDED demo-0.1.0 Install complete 2 Wed Feb 20 21:18:12 2019 SUPERSEDED demo-0.1.0 Upgrade complete 3 Wed Feb 20 21:28:48 2019 DELETED demo-0.1.0 Deletion complete

      The STATUS for REVISION 3 has changed to DELETED, indicating that your deployed instance of web has been deleted. However, although this does delete the release, it does not delete it from store. In order to delete the release completely, run the helm delete command with the --purge flag.

      In this step, you have managed application releases on Kubernetes with the Helm. If you would like to study Helm further, check out our An Introduction to Helm, the Package Manager for Kubernetes tutorial, or review the official Helm documentation.

      Next, you will set up and test the pipeline automation tool Jenkins X by using the jx CLI to create a CI/CD-ready Kubernetes cluster.

      Step 4 — Setting Up the Jenkins X Environment

      With Jenkins X, you can create your Kubernetes cluster from the ground up with pipeline automation and CI/CD solutions built in. By installing the jx CLI tool, you will be able to efficiently manage application releases, Docker images, and Helm charts, in addition to automatically promoting your applications across environments in GitHub.

      Since you will be using jx to create your cluster, you must first delete the Minikube cluster that you already have. To do this, use the following command:

      This will delete the local simulated Kubernete cluster, but will not delete the default directories created when you first installed Minikube. To clean these off your machine, use the following commands:

      • rm -rf ~/.kube
      • rm -rf ~/.minikube
      • rm -rf /etc/kubernetes/*
      • rm -rf /var/lib/minikube/*

      Once you have completely cleared Minikube from your machine, you can move on to installing the Jenkins X binary.

      First, download the compressed jx file from the official Jenkins X GitHub repository with the curl command and uncompress it with the tar command:

      • curl -L | tar xzv

      Next, move the downloaded jx file to the executable path at /usr/local/bin:

      Jenkins X comes with a Docker Registry that runs inside your Kubernetes cluster. Since this is an internal element, security measures such as self-signed certificates can cause trouble for the program. To fix this, set Docker to use insecure registries for the local IP range. To do this, create the file /etc/docker/daemon.json and open it in your text editor:

      • nano /etc/docker/daemon.json

      Add the following contents to the file:


        "insecure-registries" : [""]

      Save and exit the file. For these changes to take effect, restart the Docker service with the following command:

      To verify that you have configured Docker with insecure registries, use the following command:

      At the end of the output, you should see the following highlighted line:


      Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 15 Server Version: 18.06.1-ce Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true . . . Registry: Labels: Experimental: false Insecure Registries: Live Restore Enabled: false

      Now that you have downloaded Jenkins X and configured the Docker registry, use the jx CLI tool to create a Minikube Kubernetes cluster with CI/CD capabilities:

      • jx create cluster minikube --cpu=5 --default-admin-password=admin --vm-driver=none --memory=13314

      Here you are creating a Kubernetes cluster using Minikube, with the flag --cpu=5 to set 5 CPUs and --memory=13314 to give your cluster 13314 MBs of memory. Since Jenkins X is a robust but large program, these specifications will ensure that Jenkins X works without problems in this demonstration. Also, you are using --default-admin-password=admin to set the Jenkins X password as admin and --vm-driver=none to set up the cluster locally, as you did in Step 1.

      As Jenkins X spins up your cluster, you will receive various prompts at different times throughout the process that set the parameters for your cluster and determine how it will communicate with GitHub to manage your production environments.

      First, you will receive the following prompt:


      ? disk-size (MB) 150GB

      Press ENTER to continue. Next, you will be prompted for the name you wish to use with git, the email address you wish to use with git, and your GitHub username. Enter each of these when prompted, then press ENTER.

      Next, Jenkins X will prompt you to enter your GitHub API token:


      To be able to create a repository on GitHub we need an API Token Please click this URL,read:user,read:org,user:email,write:repo_hook,delete_repo Then COPY the token and enter in into the form below: ? API Token:

      Enter your token here, or create a new token with the appropriate permissions using the highlighted URL in the preceding code block.

      Next, Jenkins X will ask:


      ? Do you wish to use GitHub as the pipelines Git server: (Y/n) ? Do you wish to use your_GitHub_username as the pipelines Git user for GitHub server: (Y/n)

      Enter Y for both questions.

      After this, Jenkins X will prompt you to answer the following:


      ? Select Jenkins installation type: [Use arrows to move, type to filter] >Static Master Jenkins Serverless Jenkins ? Pick workload build pack: [Use arrows to move, type to filter] > Kubernetes Workloads: Automated CI+CD with GitOps Promotion Library Workloads: CI+Release but no CD

      For the prior, select Static Master Jenkins, and select Kubernetes Workloads: Automated CI+CD with GitOps Promotion for the latter. When prompted to select an organization for your environment repository, select your GitHub username.

      Finally, you will receive the following output, which verifies successful installation and provides your Jenkins X admin password.


      Creating GitHub webhook for your_GitHub_username/environment-horsehelix-production for url Jenkins X installation completed successfully ******************************************************** NOTE: Your admin password is: admin ******************************************************** Your Kubernetes context is now set to the namespace: jx To switch back to your original namespace use: jx namespace default For help on switching contexts see: To import existing projects into Jenkins: jx import To create a new Spring Boot microservice: jx create spring -d web -d actuator To create a new microservice from a quickstart: jx create quickstart

      Next, use the jx get command to receive a list of URLs that show information about your application:

      This command will yield a list similar to the following:

      Name                      URL

      You can use the URLs to view Jenkins X data about your CI/CD environment via a UI by entering the address into your browser and entering your username and password. In this case, this will be "admin" for both.

      Next, in order to ensure that the service accounts in the namespaces jx, jx-staging, and jx-production have admin privileges, modify your RBAC policies with the following commands:

      • kubectl create clusterrolebinding jx-staging1 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-staging:expose --namespace=jx-staging
      • kubectl create clusterrolebinding jx-staging2 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-staging:default --namespace=jx-staging
      • kubectl create clusterrolebinding jx-production1 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-production:expose --namespace=jx-productions
      • kubectl create clusterrolebinding jx-production2 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx-production:default --namespace=jx-productions
      • kubectl create clusterrolebinding jx-binding1 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx:expose --namespace=jx
      • kubectl create clusterrolebinding jx-binding2 --clusterrole=cluster-admin --user=admin --user=expose --group=system:serviceaccounts --serviceaccount=jx:default --namespace=jx

      Now that you have created your local Kubernetes cluster with Jenkins X functionality built in, you can move on to creating an application on the platform to test its CI/CD capabilities and experience a Jenkins X pipeline.

      Step 5 — Creating a Test Application in Your Jenkins X Environment

      With your Jenkins X environment set up in your Kubernetes cluster, you now have CI/CD infrastructure in place that can help you automate a testing pipeline. In this step, you will try this out by setting up a test application in a working Jenkins X pipeline.

      For demonstration purposes, this tutorial will use a sample RSVP application created by the CloudYuga team. You can find this application, along with other webinar materials, at the DO-Community GitHub repository.

      First, clone the sample application from the repository with the following command:

      • git clone

      Once you've cloned the repository, move into the rsvpapp directory and remove the git files:

      To initialize a git repository and a Jenkins X project for a new application, you can use jx create to start from scratch or a template, or jx import to import an existing application from a local project or git repository. For this tutorial, import the sample RSVP application by running the following command from within the application's home directory:

      Jenkins X will prompt you for your GitHub username, whether you'd like to initialize git, a commit message, your organization, and the name you would like for your repository. Answer yes to initialize git, then provide the rest of the prompts with your individual GitHub information and preferences. As Jenkins X imports the application, it will create Helm charts and a Jenkinsfile in your application's home directory. You can modify these charts and the Jenkinsfile as per your requirements.

      Since the sample RSVP application runs on port 5000 of its container, modify your charts/rsvpapp/values.yaml file to match this. Open the charts/rsvpapp/values.yaml in your text editor:

      • nano charts/rsvpapp/values.yaml

      In this values.yaml file, set service:internalPort: to 5000. Once you have made this change, your file should look like the following:


      # Default values for python.
      # This is a YAML-formatted file.
      # Declare variables to be passed into your templates.
      replicaCount: 1
        repository: draft
        tag: dev
        pullPolicy: IfNotPresent
        name: rsvpapp
        type: ClusterIP
        externalPort: 80
        internalPort: 5000
 " nginx"
          cpu: 100m
          memory: 128Mi
          cpu: 100m
          memory: 128Mi
        enabled: false

      Save and exit your file.

      Next, change the charts/preview/requirements.yaml to fit with your application. requirements.yaml is a YAML file in which developers can declare chart dependencies, along with the location of the chart and the desired version. Since our sample application uses MongoDB for database purposes, you'll need to modify the charts/preview/requirements.yaml file to list MongoDB as a dependency. Open the file in your text editor with the following command:

      • nano charts/preview/requirements.yaml

      Edit the file by adding the mongodb-replicaset entry after the alias: cleanup entry, as is highlighted in the following code block:


      # !! File must end with empty line !!
      - alias: expose
        name: exposecontroller
        version: 2.3.92
      - alias: cleanup
        name: exposecontroller
        version: 2.3.92
      - name: mongodb-replicaset
        version: 3.5.5
        # !! "alias: preview" must be last entry in dependencies array !!
        # !! Place custom dependencies above !!
      - alias: preview
        name: rsvpapp
        repository: file://../rsvpapp

      Here you have specified the mongodb-replicaset chart as a dependency for the preview chart.

      Next, repeat this process for your rsvpapp chart. Create the charts/rsvpapp/requirements.yaml file and open it in your text editor:

      • nano charts/rsvpapp/requirements.yaml

      Once the file is open, add the following, making sure that there is a single line of empty space before and after the populated lines:


      - name: mongodb-replicaset
        version: 3.5.5

      Now you have specified the mongodb-replicaset chart as a dependency for your rsvpapp chart.

      Next, in order to connect the frontend of the sample RSVP application to the MongoDB backend, add a MONGODB_HOST environment variable to your deployment.yaml file in charts/rsvpapp/templates/. Open this file in your text editor:

      • nano charts/rsvpapp/templates/deployment.yaml

      Add the following highlighted lines to the file, in addition to one blank line at the top of the file and two blank lines at the bottom of the file. Note that these blank lines are required for the YAML file to work:


      apiVersion: extensions/v1beta1
      kind: Deployment
        name: {{ template "fullname" . }}
          draft: {{ default "draft-app" .Values.draft }}
          chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
        replicas: {{ .Values.replicaCount }}
              draft: {{ default "draft-app" .Values.draft }}
              app: {{ template "fullname" . }}
      {{- if .Values.podAnnotations }}
      {{ toYaml .Values.podAnnotations | indent 8 }}
      {{- end }}
            - name: {{ .Chart.Name }}
              image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
              - name: MONGODB_HOST
                value: "mongodb://{{.Release.Name}}-mongodb-replicaset-0.{{.Release.Name}}-mongodb-replicaset,{{.Release.Name}}-mongodb-replicaset-1.{{.Release.Name}}-mongodb-replicaset,{{.Release.Name}}-mongodb-replicaset-2.{{.Release.Name}}-mongodb-replicaset:27017"
              imagePullPolicy: {{ .Values.image.pullPolicy }}
              - containerPort: {{ .Values.service.internalPort }}
      {{ toYaml .Values.resources | indent 12 }}

      With these changes, Helm will be able to deploy your application with MongoDB as its database.

      Next, examine the Jenkinsfile generated by Jenkins X by opening the file from your application's home directory:

      This Jenkinsfile defines the pipeline that is triggered every time you commit a version of your application to your GitHub repository. If you wanted to automate your code testing so that the tests are triggered every time the pipeline is triggered, you would add the test to this document.

      To demonstrate this, add a customized test case by replacing sh "python -m unittest" under stage('CI Build and push snapshot') and stage('Build Release') in the Jenkinsfile with the following highlighted lines:


      . . .
        stages {
          stage('CI Build and push snapshot') {
            when {
              branch 'PR-*'
            environment {
              PREVIEW_NAMESPACE = "$APP_NAME-$BRANCH_NAME".toLowerCase()
              HELM_RELEASE = "$PREVIEW_NAMESPACE".toLowerCase()
            steps {
              container('python') {
                sh "pip install -r requirements.txt"
                sh "python -m pytest tests/"
                sh "export VERSION=$PREVIEW_VERSION && skaffold build -f skaffold.yaml"
                sh "jx step post build --image $DOCKER_REGISTRY/$ORG/$APP_NAME:$PREVIEW_VERSION"
                dir('./charts/preview') {
                  sh "make preview"
                  sh "jx preview --app $APP_NAME --dir ../.."
          stage('Build Release') {
            when {
              branch 'master'
            steps {
              container('python') {
                // ensure we're not on a detached head
                sh "git checkout master"
                sh "git config --global credential.helper store"
                sh "jx step git credentials"
                // so we can retrieve the version in later steps
                sh "echo $(jx-release-version) > VERSION"
                sh "jx step tag --version $(cat VERSION)"
                sh "pip install -r requirements.txt"
                sh "python -m pytest tests/"
                sh "export VERSION=`cat VERSION` && skaffold build -f skaffold.yaml"
                sh "jx step post build --image $DOCKER_REGISTRY/$ORG/$APP_NAME:$(cat VERSION)"
      . . .

      With the added lines, the Jenkins X pipeline will install dependencies and carry out a Python test whenever you commit a change to your application.

      Now that you have changed the sample RSVP application, commit and push these changes to GitHub with the following commands:

      • git add *
      • git commit -m update
      • git push

      When you push these changes to GitHub, you will trigger a new build of your application. If you open the Jenkins UI by navigating to and entering "admin" for your username and password, you will find information about your new build. If you click "Build History" from the menu on the left side of the page, you should see a history of your committed builds. If you click on the blue icon next to a build then select "Console Ouput" from the lefthand menu, you will find the console output for the automated steps in your pipeline. Scrolling to the end of this output, you will find the following message:


      . . . Finished: SUCCESS

      This means that your application has passed your customized tests and is now successfully deployed.

      Once Jenkins X builds the application release, it will promote the application to the staging environment. To verify that your application is running, list the applications running on your Kubernetes cluster by using the following command:

      You will receive output similar to the following:


      APPLICATION STAGING PODS URL rsvpapp 0.0.2 1/1

      From this, you can see that Jenkins X has deployed your application in your jx-staging environment as version 0.0.2. The output also shows the URL that you can use to access your application. Visiting this URL will show you the sample RSVP application:

      Sample RSVP Application in the Staging Environment

      Next, check out the activity of your application with the following command:

      • jx get activity -f rsvpapp

      You will receive output similar to the following:


      STEP STARTED AGO DURATION STATUS your_GitHub_username/rsvpappv/master #1 3h42m23s 4m51s Succeeded Version: 0.0.1 Checkout Source 3h41m52s 6s Succeeded CI Build and push snapshot 3h41m46s NotExecuted Build Release 3h41m46s 56s Succeeded Promote to Environments 3h40m50s 3m17s Succeeded Promote: staging 3h40m29s 2m36s Succeeded PullRequest 3h40m29s 1m16s Succeeded PullRequest: Merge SHA: dc33d3747abdacd2524e8c22f0b5fbb2ac3f6fc7 Update 3h39m13s 1m20s Succeeded Status: Success at: Promoted 3h39m13s 1m20s Succeeded Application is at: Clean up 3h37m33s 1s Succeeded your_GitHub_username/rsvpappv/master #2 28m37s 5m57s Succeeded Version: 0.0.2 Checkout Source 28m18s 4s Succeeded CI Build and push snapshot 28m14s NotExecuted Build Release 28m14s 56s Succeeded Promote to Environments 27m18s 4m38s Succeeded Promote: staging 26m53s 4m0s Succeeded PullRequest 26m53s 1m4s Succeeded PullRequest: Merge SHA: 976bd5ad4172cf9fd79f0c6515f5006553ac6611 Update 25m49s 2m56s Succeeded Status: Success at: Promoted 25m49s 2m56s Succeeded Application is at: Clean up 22m40s 0s Succeeded

      Here you are getting the Jenkins X activity for the RSVP application by applying a filter with -f rsvpapp.

      Next, list the pods running in the jx-staging namespace with the following command:

      • kubectl get pod -n jx-staging

      You will receive output similar to the following:

      NAME                                 READY     STATUS    RESTARTS   AGE
      jx-staging-mongodb-replicaset-0      1/1       Running   0          6m
      jx-staging-mongodb-replicaset-1      1/1       Running   0          6m
      jx-staging-mongodb-replicaset-2      1/1       Running   0          5m
      jx-staging-rsvpapp-c864c4844-4fw5z   1/1       Running   0          6m

      This output shows that your application is running in the jx-staging namespace, along with three pods of the backend MongoDB database, adhering to the changes you made to the YAML files earlier.

      Now that you have run a test application through the Jenkins X pipeline, you can try out promoting this application to the production environment.

      To finish up this demonstration, you will complete the CI/CD process by promoting the sample RSVP application to your jx-production namespace.

      First, use jx promote in the following command:

      • jx promote rsvpapp --version=0.0.2 --env=production

      This will promote the rsvpapp application running with version=0.0.2 to the production environment. Throughout the build process, Jenkins X will prompt you to enter your GitHub account information. Answer these prompts with your individual responses as they appear.

      After successful promotion, check the list of applications:

      You will receive output similar to the following:



      With this PRODUCTION information, you can confirm that Jenkins X has promoted rsvpapp to the production environment. For further verification, visit the production URL in your browser. You should see the working application, now runnning from "production":

      Sample RSVP Application in the Production Environment

      Finally, list your pods in the jx-production namespace.

      • kubectl get pod -n jx-production

      You will find that rsvpapp and the MongoDB backend pods are running in this namespace:

      NAME                                     READY     STATUS    RESTARTS   AGE
      jx-production-mongodb-replicaset-0       1/1       Running   0          1m
      jx-production-mongodb-replicaset-1       1/1       Running   0          1m
      jx-production-mongodb-replicaset-2       1/1       Running   0          55s
      jx-production-rsvpapp-54748d68bd-zjgv7   1/1       Running   0          1m 

      This shows that you have successfully promoted the RSVP sample application to your production environment, simulating the production-ready deployment of an application at the end of a CI/CD pipeline.


      In this tutorial, you used Helm to manage packages on a simulated Kubernetes cluster and customized a Helm chart to package and deploy your own application. You also set up a Jenkins X environment on your Kubernetes cluster and run a sample application through a CI/CD pipeline from start to finish.

      You now have experience with these tools that you can use when building a CI/CD system on your own Kubernetes cluster. If you'd like to learn more about Helm, check out our An Introduction to Helm, the Package Manager for Kubernetes and How To Install Software on Kubernetes Clusters with the Helm Package Manager articles. To explore further CI/CD tools on Kubernetes, you can read about the Istio service mesh in the next tutorial in this webinar series.

      Source link

      The 8 Best Web Management Tools for Small Businesses in 2019

      From site design to social media and everything in between, managing your web presence is integral in today’s market. There are several reasons why you need a strong online presence: it reinforces your brand, boosts your marketing efforts, and most importantly, helps you connect with your customers.

      But what if you’ve got a local clientele or are a brick-and-mortar operation that’s not really interested in doing the whole e-commerce thing? Do you really need a small-business website?

      The answer is an internet-troll-style, all-caps, gigantic YES: 97 percent of consumers use the web to search for local businesses. If you want your small business to reach its full potential, you need to have an online presence.

      But where do you start? After all, there are thousands of tools out there that claim they help with web management. So we’ve put our fingers on the keyboard and nose to the grindstone — gross, right? — to research the best web management tools for your small business. Here’s what we found.

      Web Design

      When it comes to web design you’ve got several options. Of course, you can always hire a professional team from a trusted firm to tackle your web design, but experts don’t come cheap. If you’re looking for a more cost-effective method, you’ll be pleased to learn that there are several programs that are easy to navigate, have beautiful templates, and provide easy click-to-edit functionality to make creating a beautiful website easy — even if you don’t know how to code or aren’t a professional designer. Here are some of the best.

      1. WordPress

      If you’re at all web savvy, WordPress is an excellent choice. WordPress is a content management system (CMS) that makes it easy to regularly update your website with fresh blog posts, news stories, and more. WordPress does have a slight learning curve, but it’s relatively easy to tackle and you’ll be pleased with the number of features.

      • Flexibility — WordPress is extremely versatile. You can create a blog, a portfolio, a business website, an online community, an online store, and basically anything else you can think of.
      • Simplicity — Not only is WordPress flexible, but it’s also simple to use. With WordPress, you don’t have to know how to code to get a responsive website up in minutes. Plus, tools like DreamPress are specifically built to make maintaining your site and keeping it secure really easy.
      • Popular — WordPress is one of the most popular web design tools on the market. That means there are thousands of pre-designed themes, useful plugins, and resources to help you build, modify, and update your site with ease.
      • Cost — Since software is free, it’s a budget-friendly option that can scale with your business as you grow and need more features.

      Get More with DreamPress

      DreamPress Plus and Pro users get access to Jetpack Professional (and 200+ premium themes) at no added cost!

      2. Remixer

      Remixer is another top-of-the-line website building tool that was whipped up fresh in DreamHost’s developer kitchen. Here’s why it’s great: if you need a DIY website that doesn’t look homemade, Remixer is a click-to-edit solution. So what else does Remixer have going for it? Glad you asked.

      • Responsive — With Remixer, you can rest assured that your website is 100 percent responsive. This means no matter what device your visitors are using to find your site, they’ll have a great experience. In 2018, a mobile-optimized website is a must for small-biz owners.
      • Easy — Remixer is designed with ease in mind. That’s why the click-to-edit interface makes it easy to import your own images. If you don’t have your own art, the royalty-free image library takes care of that too.
      • Quick — Just a few clicks on Remixer and you can get a website up and running in 10 minutes. Yeah, we timed it.
      • Easy to Export  You can start your site in Remixer and then easily export it to WordPress when you’re ready to add e-commerce or blogging functionality.

      Need a Beautiful Website?

      Design it yourself with Remixer, our easy-to-use website builder. No coding required.

      E-Commerce Software

      If you want e-commerce capabilities, we’d recommend building your website with WordPress — the flexibility and scalability are ideal for online stores. But remember: WordPress doesn’t come with an e-commerce solution out of the box. You’ll have to add that functionality, either via a plugin or an additional platform, to create a digital shopping cart.

      3. WooCommerce

      WooCommerce is a popular WordPress plugin and one of the best e-commerce solutions on the market. And it’s easy to get started! Basic features to help you manage payment, shipping, and other common tasks come baked in. If you need additional options, however, it’s easy to find extensions to add functionality.

      • Budget-Friendly — Both software and WooCommerce are completely free, as are some of the extensions (most of the others range from around $50 to $100). Getting your online store up and running doesn’t have to burn a hole in your pocket.
      • Scalable — WooCommerce makes scaling from small business to larger venture easy. For example, if you need more payment gateways, simply download and install a relevant extension or plugin.
      • Secure — Security is vital for every website but especially if you’re managing transactions. WordPress’ dedication to security and frequent updates will help protect your site. Additionally, customers using DreamHost’s managed WordPress options are protected by a built-in firewall that eliminates the need for additional security plugins.
      • Search Engine Optimized — WooCommerce itself is light on SEO-related features. It’s built using code optimized for SEO, and there are a few relevant extensions you can add, such as SEO Friendly Images. However, if you really want to improve your store’s chances of getting to the first page of Google, you can download a WordPress SEO plugin.

      Your Store Deserves WooCommerce Hosting

      Sell anything, anywhere, anytime on the world’s biggest eCommerce platform.

      4. Shopify

      Shopify is a subscription-based, e-commerce platform that makes it easy for beginners to build and customize an online store in very little time. It also provides a “guru” service to guide you through the creation and management of your e-commerce site.

      • Reliable — Shopify is one of the largest e-commerce solutions on the market. Because it requires a monthly subscription — plans currently start at $29 per month — you can count on Shopify’s rock-solid performance.
      • Integratable — It’s easy for DreamHost customers to integrate a Shopify store with your site. There’s also an app store where you can download add-ons that provide functionality such as social media, shipping, and accounting.
        Support — Shopify provides support through its comprehensive help center, where you can find everything from tutorials to troubleshooting guides. You also get access to 24/7 support via chat, email, or phone.

      Still wondering whether you should opt for WooCommerce or Shopify when building your e-commerce site? Wonder no more. We’ve put together a comprehensive guide to help you parse out which platform might be more suitable for your website.

      Social Media

      Even a small business can have a large social media presence. The social tools below will allow you to expand your web presence all in one integrated interface. Be in several places at once? It’s every small business owner’s dream!

      5. HootSuite

      HootSuite integrates with Facebook, Facebook Pages, Twitter, Instagram, Google+, Google+ Pages, LinkedIn, FourSquare, MySpace, YouTube, and WordPress. It allows you to schedule posts ahead of time, focusing on peak performance times for each platform.

      • Convenience — If you’re sick of switching between your social media profiles just to push out daily updates, then you’re going to love HootSuite. With HootSuite, you can manage all your social platforms from one location.
      • Collaboration — Many small businesses have several people creating content and posting across channels. If you don’t have a cohesive system, you’re setting yourself up for a social snafu. HootSuite gets everyone on the same page.
      • Reputation Management — HootSuite makes it possible to never miss a mention or complaint that your team needs to address.

      6. Buffer

      Buffer supports up to 25 social accounts, allowing you to post across all your platforms from one interface. Here are some of Buffer’s other top features.

      • Trends — Buffer has integrated analytics and insights, making it easier to tweak your social strategy based on data.
      • Scheduling — Buffer allows you to create a custom schedule for each day. You can do it daily, monthly, or annually — basically whenever it’s convenient.
      • Insights — You’ll never have to wonder when you should share your next Instagram pic or Facebook missive. Buffer keeps track of your followers so you know when it’s the optimal time to post.

      7. Everypost

      Everypost makes it easy to curate content from across the web, schedule your posts, and integrates with Facebook, Twitter, Google+, Linkedin, Pinterest, and tumblr.

      • Analytics — You can social smarter with the analytics provided by Everypost. The dashboard is sleek and easy to use.
      • Curation — Everypost helps you curate content directly within the app — no switching around to find shareable content, design content, and post content.
      • Customization — You can maximize the potential of each post you create. This helps you reach all of your audience members, no matter what platform they are on.


      It’s not enough to build your website and forget it; you’ve got to be strategic about getting your brand out into the world — and in front of the eyes of your potential customers — as much as possible. Even if your business is a brick-and-mortar deal, promoting your website and digital offerings will usher local Googlers into your doors.

      8. HubSpot

      HubSpot offers a free marketing tool and WordPress plugin to help keep track of potential customers and assist you with lead conversion — that is, converting a casual browser into a committed buyer.

      • Capture — HubSpot makes it easy to grab website visitors’ email addresses by helping you create a pop-up invitation or another module. It can even pull and track information from any form submission on your website — no matter what tool or plugin.
      • Track — Along with keeping track of visitors’ email addresses and activity on your website (purchases, time spent on page, etc.), you’ll know which other websites your potential customers have visited.  
      • Convert — Analytics displayed on a simple dashboard will help you know what’s working for your site (and what isn’t) and how to target marketing emails to bring your customers back.
      • Simple — The HubSpot WordPress plugin is simple to use, even for the non-techie, and it plays nicely with other tools such as Shopify.

      Want to Keep It Simple?

      Obviously, there are several tools out there to help you effectively manage your online presence. But you don’t have to overwhelm yourself by investing in every option on the market! If you’re brand new to the web, use Remixer to get your website up quickly. Then you can add some of the other options on this list to build your brand online.

      Source link

      Secrets Management with Terraform

      Updated by Linode Contributed by Linode

      Terraform is an Infrastructure as Code (IaC) tool that allows you to write declarative code to manage your infrastructure. In order to implement IaC with Terraform it is necessary to supply secrets, such as server passwords and API tokens, within your code. This guide will discuss methods for securing those secrets within Terraform.

      Keeping Secrets Out of .tf Files

      In Terraform, .tf files contain the declarative code used to create, manage, and destroy infrastructure. This code is often committed to a version control system like Git, using a platform like GitHub, and shared within a team. Because it is easy for this information to become public-facing, it is important that you make sure your committed code is free of secrets.

      Input Variables

      Terraform configurations in .tf files can accept values from input variables. These variables are included in your configuration using Terraform’s interpolation syntax.

      For example, you might have a file with a provider block that requires an API access token. The token variable definition is declared inside your .tf file and is then interpolated inside the provider declaration with the "${var.token}" syntax:
      variable "token" {
        description = "Your API access token"
      provider "linode" {
          token = "${var.token}"

      Variable definitions are written in .tf files. In this example, it’s the same file as your provider configuration, but the definition could have been in a separate .tf file too.


      Your variable definitions can have default values assigned to them. Here’s an example that encodes Linode’s Newark data center as the default value for a region variable:
      variable "region" {
        description = "The region to deploy Linode instances in"
        default = "us-east"

      You could later use this variable when declaring your Linode instances.

      Assigning Variable Values in a File

      The values assigned to your variables (aside from default values) are not included in the variable definitions in your .tf files. Instead, the values are stored in separate files with the .tfvars extension. When Terraform runs a command like plan or apply, it automatically looks through the working directory for a file named terraform.tfvars, or for files with the .auto.tfvars extension.

      Here’s an example terraform.tfvars which supplies a value for the token variable from the previous example:

      token = 'your-token-value'

      You would then add the terraform.tfvars file to your .gitignore file and keep it out of version control. This strategy allows you to safely commit the file.

      For ease of use with large terraform.tfvars files, it might be beneficial to include an example terraform.tfvars.example in your Git repository with all of the variable names recorded (but none of the values entered). Team members could then copy this example into their local repository’s terraform.tfvars and enter the appropriate values.


      Variable value files with names that don’t match terraform.tfvars or *.auto.tfvars can be specified with the -var-file option:

      terraform apply -var-file=myvars.tfvars

      Supplying multiple .tfvars files is another way to further separate secret variables and non-secret variables; e.g.:

      terraform apply 

      Assigning Values in Environment Variables

      Terraform allows you to keep input variable values in environment variables. These variables have the prefix TF_VAR_ and are supplied at the command line. Using the above example of an API access token, you could export the variable and use it like so:

      export TF_VAR_token=your-token-value
      terraform apply

      You could also include the variable on the same line when running terraform plan or terraform apply:

      TF_VAR_token=your-token-value terraform apply


      This method commits the environment variable to your shell’s history, so take care when using this method.

      Assigning Values in Command-Line Flags

      Variable values can be set with the -var option:

      terraform apply -var 'token=your-token-value'


      This method commits the command-line variable to your shell’s history, so take care when using this method.

      Supply Variables at Prompt

      If Terraform does not find a default value for a defined variable; or a value from a .tfvars file, environment variable, or CLI flag; it will prompt you for a value before running an action:

      $ terraform plan
        Your API access token
        Enter a value:

      This method is a bit easier to use than supplying environment variables, and has the added benefit of displaying the description you set up when defining your variable.

      How to Manage Your State File

      While it is relatively easy to keep secrets out of .tf files using any of the above methods, there is another file you need to be aware of when managing secrets, and that is the terraform.tfstate file.

      This state file contains a JSON object that holds your managed infrastructure’s current state. This state is a snapshot of the various attributes of your infrastructure at the time it was last modified. It is generated on terraform apply and is a necessary part of the Terraform process, as it maps the declarative code of your .tf files to your real world infrastructure.

      As of the writing of this guide, sensitive information used to generate your Terraform state can be stored as plain text in the terraform.tfstate file. For example, if you are working with the Linode provider and have supplied a root password for your Linode instance, that root password will be stored as plain text in the state file. Avoid checking your terraform.tfstate file into your version control repository. Instead, the following are some strategies for storing and sharing your state files.

      Remote Backends

      Terraform backends allow the user to securely store their state in a remote location, such as a key/value store like Consul, or an S3 compatible bucket storage like Minio. This allows the Terraform state to be read from the remote store, and because the state only ever exists locally in memory, there is no worry about storing secrets in plain text.

      Some backends, like Consul, also allow for state locking. If one user is applying a state, another user will be unable to make any changes.

      Using a Terraform backend is the preferred way to share a Terraform state file.

      Encrypting Secrets

      Third-party tools exist that allow you to encrypt your secrets. If you encrypt the secrets in your terraform.tfstate (or your .tfvars files), you can check them into version control securely:

      • git-crypt allows you to encrypt files when they are committed to a Git repository. git-crypt also decrypts files when they are checked out.


        You must initialize git-crypt in a repository before committing your state file or variable value files, or they will not be eligible for encryption.

      • Terrahelp allows you to encrypt and decrypt a whole state file, or just the variables you have include in your terraform.tfvars file.

      Use a Dummy Password

      It is possible to supply a dummy password to Terraform and later change that password manually to a more secure one. For instance, if you were to create a Linode instance with a dummy root password, you could later change that password from the command line or in the Linode Manager.


      Any attempt to change the password in a .tf file will result in the creation of new resources on terraform apply.

      Privatize Version Control

      If you are unwilling or unable to use the above options to help manage your state file, and if you are using a platform like GitHub or GitLab to share your state files, then at minimum the repository should be private.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.

      Source link