Skip to main content
Warning This document has not been updated for a while now. It may be out of date.
Last updated: 26 Apr 2021

govuk-puppet: adding-a-new-app

See also the developer docs page on setting up a new Rails application.

In the below code examples and filenames, replace my-app and my_app with your application's name.

If your application's name has dashes in it:

  • my-app should have dashes in it
  • my_app should have dashes replaced with underscores

For example, the account-api Puppet class file is called account_api.pp, and its db_name is account-api_production.

Create the Puppet class definitions

Create the app class

Create a new file in modules/govuk/manifests/apps named my_app.pp.

First add the Puppet class documentation:

# == Class: govuk::apps::my_app
#
# Read more: https://github.com/alphagov/my-app
#
# === Parameters
# [*port*]
#   What port the app should run on.
#
# [*enabled*]
#   Whether to install or uninstall the app. Defaults to true (install on all enviroments)
#
# [*secret_key_base*]
#   The key for Rails to use when signing/encrypting sessions
#
# [*sentry_dsn*]
#   The app-specific URL used by Sentry to report exceptions
#

If your app uses GDS-SSO for authentication, include the oauth_ parameters:

# [*oauth_id*]
#   The OAuth ID used by GDS-SSO to identify the app to GOV.UK Signon
#
# [*oauth_secret*]
#   The OAuth secret used by GDS-SSO to authenticate the app to GOV.UK Signon
#

If your app uses a database, include the db_ parameters:

# [*db_hostname*]
#   The hostname of the database server to use for in DATABASE_URL environment variable
#
# [*db_username*]
#   The username to use for the DATABASE_URL environment variable
#
# [*db_password*]
#   The password to use for the DATABASE_URL environment variable
#
# [*db_port*]
#   The port of the database server to use in the DATABASE_URL.
#   Default: undef
#
# [*db_name*]
#   The database name to use for the DATABASE_URL environment variable
#

Then add the class. Omit the oauth_ and db_ parameters if your app does not need them:

class govuk::apps::my_app (
  $port,
  $enabled = true,
  $secret_key_base = undef,
  $sentry_dsn = undef,
  $oauth_id = undef,
  $oauth_secret = undef,
  $db_username = 'my-app',
  $db_hostname = undef,
  $db_port = undef,
  $db_password = undef,
  $db_name = 'my-app_production',
) {
  $app_name = 'my-app'

  $ensure = $enabled ? {
    true  => 'present',
    false => 'absent',
  }

  # see modules/govuk/manifests/app.pp for more options
  govuk::app { $app_name:
    ensure                     => $ensure,
    app_type                   => 'rack',
    port                       => $port,
    sentry_dsn                 => $sentry_dsn,
    vhost_ssl_only             => true,
    has_liveness_health_check  => true,
    has_readiness_health_check => true,
    deny_framing               => true,
    asset_pipeline             => true,
  }

  Govuk::App::Envvar {
    app               => $app_name,
    ensure            => $ensure,
    notify_service    => $enabled,
  }

  govuk::app::envvar {
    "${title}-SECRET_KEY_BASE":
      varname => 'SECRET_KEY_BASE',
      value   => $secret_key_base;
  }

If your app uses GDS-SSO, set the required environment variables:

  govuk::app::envvar {
    "${title}-GDS_SSO_OAUTH_ID":
      varname => 'GDS_SSO_OAUTH_ID',
      value   => $oauth_id;
    "${title}-GDS_SSO_OAUTH_SECRET":
      varname => 'GDS_SSO_OAUTH_SECRET',
      value   => $oauth_secret;
  }

If your app uses a database, set the database URL:

  govuk::app::envvar::database_url { $app_name:
    type     => 'postgresql',
    username => $db_username,
    password => $db_password,
    host     => $db_hostname,
    port     => $db_port,
    database => $db_name,
  }

Then end the class definition:

}

Create the database class

If your app does not use a database, skip this subsection.

Create a new file in modules/govuk/manifests/apps/my_app named db.pp, with the following contents:

# == Class: govuk::apps::my_app::db
#
# === Parameters
#
# [*backend_ip_range*]
#   Backend IP addresses to allow access to the database.
#
# [*allow_auth_from_lb*]
#   Whether to allow this user to authenticate for this database from
#   the load balancer using its password.
#   Default: false
#
# [*lb_ip_range*]
#   Network range for the load balancer.
#
# [*rds*]
#   Whether to use RDS i.e. when running on AWS
#
# [*username*]
#   The DB instance username.
#
# [*password*]
#   The DB instance password.
#
# [*db_name*]
#   The DB instance name.
#
class govuk::apps::my_app::db (
  $backend_ip_range = '10.3.0.0/16',
  $allow_auth_from_lb = false,
  $lb_ip_range = undef,
  $rds = false,
  $username = 'my-app',
  $password = undef,
  $db_name = 'my-app_production',
) {
  govuk_postgresql::db { $db_name:
    user                    => $username,
    password                => $password,
    allow_auth_from_backend => true,
    backend_ip_range        => $backend_ip_range,
    allow_auth_from_lb      => $allow_auth_from_lb,
    lb_ip_range             => $lb_ip_range,
    rds                     => $rds,
  }
}

Include the class in the modules/govuk/manifests/nodes/db_admin.pp file:

-> class { '::govuk::apps::my_app::db': }

Configure the hieradata

Choose a port number

Find the list of used port numbers by looking in hieradata_aws/common.yaml, then give your app the next unassigned number:

govuk::apps::my_app::port: 999999

Configure database access

If your app does not use a database, skip this subsection.

Add the following configuration to hieradata_aws/common.yaml:

govuk::apps::my_app::db_hostname: "postgresql-primary"
govuk::apps::my_app::db::backend_ip_range: "%{hiera('environment_ip_prefix')}.3.0/24"
govuk::apps::my_app::db::allow_auth_from_lb: true
govuk::apps::my_app::db::lb_ip_range: "%{hiera('environment_ip_prefix')}.0.0/16"
govuk::apps::my_app::db::rds: true

Add your application to the list of deployable applications

Add your application to the deployable_applications list in hieradata_aws/common.yaml:

deployable_applications: &deployable_applications
  my-app: {}

Enable deployments from CI to integration

Add your application to the govuk_jenkins::jobs::deploy_app_downstream::applications list in hieradata_aws/class/integration/ci_master.yaml.

govuk_jenkins::jobs::deploy_app_downstream::applications:
  my-app: {}

Enable the deployment dashboard

Add your application to the grafana::dashboards::application_dashboards lists in:

  • hieradata_aws/common.yaml
  • hieradata_aws/integration.yaml
grafana::dashboards::application_dashboards:
  my-app: {}

Enable your app in all environments

Add your app to the apps list for the relevant node_class in:

  • hieradata_aws/common.yaml
  • hieradata_aws/production.yaml
  • hieradata_aws/staging.yaml
node_class: &node_class
  machine_class:
    apps:
      - my-app

Deploy Puppet

Once these changes are merged and deployed, you should be able to deploy your app with the Deploy_App Jenkins job.