2020-10-24 23:57:45 +05:30
---
2023-06-20 00:43:36 +05:30
stage: Deploy
group: Environments
2022-11-25 23:54:43 +05:30
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
2020-10-24 23:57:45 +05:30
---
2021-10-27 15:23:28 +05:30
# Deployment safety **(FREE)**
2020-06-23 00:09:42 +05:30
2022-10-11 01:57:18 +05:30
[Deployment jobs ](../jobs/index.md#deployment-jobs ) are a specific kind of CI/CD
2022-07-16 23:28:13 +05:30
job. They can be more sensitive than other jobs in a pipeline,
2020-06-23 00:09:42 +05:30
and might need to be treated with extra care. GitLab has several features
that help maintain deployment security and stability.
You can:
2023-01-13 00:05:48 +05:30
- Set appropriate roles to your project. See [Project members permissions ](../../user/permissions.md#project-members-permissions )
for the different user roles GitLab supports and the permissions of each.
2020-06-23 00:09:42 +05:30
- [Restrict write-access to a critical environment ](#restrict-write-access-to-a-critical-environment )
2020-07-28 23:09:34 +05:30
- [Prevent deployments during deploy freeze windows ](#prevent-deployments-during-deploy-freeze-windows )
2021-03-08 18:12:59 +05:30
- [Protect production secrets ](#protect-production-secrets )
- [Separate project for deployments ](#separate-project-for-deployments )
2020-06-23 00:09:42 +05:30
If you are using a continuous deployment workflow and want to ensure that concurrent deployments to the same environment do not happen, you should enable the following options:
- [Ensure only one deployment job runs at a time ](#ensure-only-one-deployment-job-runs-at-a-time )
2023-01-13 00:05:48 +05:30
- [Prevent outdated deployment jobs ](#prevent-outdated-deployment-jobs )
< i class = "fa fa-youtube-play youtube" aria-hidden = "true" > < / i >
For an overview, see [How to secure your CD pipelines/workflow ](https://www.youtube.com/watch?v=Mq3C1KveDc0 ).
2020-06-23 00:09:42 +05:30
## Restrict write access to a critical environment
2021-09-30 23:02:18 +05:30
By default, environments can be modified by any team member that has at least the
2022-04-04 11:22:00 +05:30
Developer role.
2020-06-23 00:09:42 +05:30
If you want to restrict write access to a critical environment (for example a `production` environment),
you can set up [protected environments ](protected_environments.md ).
## Ensure only one deployment job runs at a time
Pipeline jobs in GitLab CI/CD run in parallel, so it's possible that two deployment
jobs in two different pipelines attempt to deploy to the same environment at the same
time. This is not desired behavior as deployments should happen sequentially.
2021-09-30 23:02:18 +05:30
You can ensure only one deployment job runs at a time with the [`resource_group` keyword ](../yaml/index.md#resource_group ) in your `.gitlab-ci.yml` .
2020-06-23 00:09:42 +05:30
For example:
```yaml
deploy:
2021-03-08 18:12:59 +05:30
script: deploy-to-prod
resource_group: prod
2020-06-23 00:09:42 +05:30
```
Example of a problematic pipeline flow **before** using the resource group:
1. `deploy` job in Pipeline-A starts running.
1. `deploy` job in Pipeline-B starts running. *This is a concurrent deployment that could cause an unexpected result.*
1. `deploy` job in Pipeline-A finished.
1. `deploy` job in Pipeline-B finished.
The improved pipeline flow **after** using the resource group:
1. `deploy` job in Pipeline-A starts running.
1. `deploy` job in Pipeline-B attempts to start, but waits for the first `deploy` job to finish.
1. `deploy` job in Pipeline-A finishes.
1. `deploy` job in Pipeline-B starts running.
2021-11-18 22:05:49 +05:30
For more information, see [Resource Group documentation ](../resource_groups/index.md ).
2020-06-23 00:09:42 +05:30
2023-01-13 00:05:48 +05:30
## Prevent outdated deployment jobs
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25276) in GitLab 12.9.
> - In GitLab 15.5, the behavior was [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/363328) to prevent outdated job runs.
2020-06-23 00:09:42 +05:30
2022-07-16 23:28:13 +05:30
The effective execution order of pipeline jobs can vary from run to run, which
2022-10-11 01:57:18 +05:30
could cause undesired behavior. For example, a [deployment job ](../jobs/index.md#deployment-jobs )
2022-07-16 23:28:13 +05:30
in a newer pipeline could finish before a deployment job in an older pipeline.
This creates a race condition where the older deployment finishes later,
2020-06-23 00:09:42 +05:30
overwriting the "newer" deployment.
2023-01-13 00:05:48 +05:30
You can prevent older deployment jobs from running when a newer deployment
job is started by enabling the [Prevent outdated deployment jobs ](../pipelines/settings.md#prevent-outdated-deployment-jobs ) feature.
When an older deployment job starts, it fails and is labeled:
- `failed outdated deployment job` in the pipeline view.
- `The deployment job is older than the latest deployment, and therefore failed.`
when viewing the completed job.
When an older deployment job is manual, the play button is disabled with a message
`This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run.` .
Job age is determined by the job start time, not the commit time, so a newer commit
can be prevented in some circumstances.
### How to rollback to an outdated deployment
2020-06-23 00:09:42 +05:30
2023-01-13 00:05:48 +05:30
> In GitLab 15.6, [rollback via job retry was introduced back](https://gitlab.com/gitlab-org/gitlab/-/issues/378359).
In some cases, you need to rollback to an outdated deployment.
This feature explicitly allows rollback via [Environment Rollback ](index.md#environment-rollback ),
so that you can quickly rollback in an urgent case.
Alternatively, you can run a new pipeline with a previous commit. It contains newer deployment jobs than the latest deployment.
### Example
Example of a problematic pipeline flow **before** enabling Prevent outdated deployment jobs:
2020-06-23 00:09:42 +05:30
2021-04-17 20:07:23 +05:30
1. Pipeline-A is created on the default branch.
1. Later, Pipeline-B is created on the default branch (with a newer commit SHA).
2020-06-23 00:09:42 +05:30
1. The `deploy` job in Pipeline-B finishes first, and deploys the newer code.
1. The `deploy` job in Pipeline-A finished later, and deploys the older code, **overwriting** the newer (latest) deployment.
2023-01-13 00:05:48 +05:30
The improved pipeline flow **after** enabling Prevent outdated deployment jobs:
2020-06-23 00:09:42 +05:30
2021-04-17 20:07:23 +05:30
1. Pipeline-A is created on the default branch.
1. Later, Pipeline-B is created on the default branch (with a newer SHA).
2020-06-23 00:09:42 +05:30
1. The `deploy` job in Pipeline-B finishes first, and deploys the newer code.
2023-01-13 00:05:48 +05:30
1. The `deploy` job in Pipeline-A fails, so that it doesn't overwrite the deployment from the newer pipeline.
2020-06-23 00:09:42 +05:30
2020-07-28 23:09:34 +05:30
## Prevent deployments during deploy freeze windows
2020-06-23 00:09:42 +05:30
If you want to prevent deployments for a particular period, for example during a planned
2020-07-28 23:09:34 +05:30
vacation period when most employees are out, you can set up a [Deploy Freeze ](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze ).
2020-06-23 00:09:42 +05:30
During a deploy freeze period, no deployment can be executed. This is helpful to
ensure that deployments do not happen unexpectedly.
2022-04-04 11:22:00 +05:30
2021-03-08 18:12:59 +05:30
## Protect production secrets
Production secrets are needed to deploy successfully. For example, when deploying to the cloud,
cloud providers require these secrets to connect to their services. In the project settings, you can
2023-03-17 16:20:25 +05:30
define and protect CI/CD variables for these secrets. [Protected variables ](../variables/index.md#protect-a-cicd-variable )
2021-03-08 18:12:59 +05:30
are only passed to pipelines running on [protected branches ](../../user/project/protected_branches.md )
or [protected tags ](../../user/project/protected_tags.md ).
The other pipelines don't get the protected variable. You can also
[scope variables to specific environments ](../variables/where_variables_can_be_used.md#variables-with-an-environment-scope ).
We recommend that you use protected variables on protected environments to make sure that the
secrets aren't exposed unintentionally. You can also define production secrets on the
2021-09-04 01:27:46 +05:30
[runner side ](../runners/configure_runners.md#prevent-runners-from-revealing-sensitive-information ).
2022-04-04 11:22:00 +05:30
This prevents other users with the Maintainer role from reading the secrets and makes sure
2022-01-26 12:08:38 +05:30
that the runner only runs on protected branches.
2021-03-08 18:12:59 +05:30
For more information, see [pipeline security ](../pipelines/index.md#pipeline-security-on-protected-branches ).
## Separate project for deployments
2022-01-26 12:08:38 +05:30
All users with the Maintainer role for the project have access to production secrets. If you need to limit the number of users
2021-03-08 18:12:59 +05:30
that can deploy to a production environment, you can create a separate project and configure a new
permission model that isolates the CD permissions from the original project and prevents the
2022-01-26 12:08:38 +05:30
original users with the Maintainer role for the project from accessing the production secret and CD configuration. You can
2022-10-11 01:57:18 +05:30
connect the CD project to your development projects by using [multi-project pipelines ](../pipelines/downstream_pipelines.md#multi-project-pipelines ).
2021-03-08 18:12:59 +05:30
2022-07-16 23:28:13 +05:30
## Protect `.gitlab-ci.yml` from change
2021-03-08 18:12:59 +05:30
A `.gitlab-ci.yml` may contain rules to deploy an application to the production server. This
deployment usually runs automatically after pushing a merge request. To prevent developers from
2021-11-11 11:23:49 +05:30
changing the `.gitlab-ci.yml` , you can define it in a different repository. The configuration can
2021-03-08 18:12:59 +05:30
reference a file in another project with a completely different set of permissions (similar to
[separating a project for deployments ](#separate-project-for-deployments )).
2021-11-11 11:23:49 +05:30
In this scenario, the `.gitlab-ci.yml` is publicly accessible, but can only be edited by users with
2021-03-08 18:12:59 +05:30
appropriate permissions in the other project.
2021-09-30 23:02:18 +05:30
For more information, see [Custom CI/CD configuration path ](../pipelines/settings.md#specify-a-custom-cicd-configuration-file ).
2020-06-23 00:09:42 +05:30
2022-03-02 08:16:31 +05:30
## Require an approval before deploying
Before promoting a deployment to a production environment, cross-verifying it with a dedicated testing group is an effective way to ensure safety. For more information, see [Deployment Approvals ](deployment_approvals.md ).
2020-06-23 00:09:42 +05:30
## Troubleshooting
### Pipelines jobs fail with `The deployment job is older than the previously succeeded deployment job...`
2023-01-13 00:05:48 +05:30
This is caused by the [Prevent outdated deployment jobs ](../pipelines/settings.md#prevent-outdated-deployment-jobs ) feature.
2020-06-23 00:09:42 +05:30
If you have multiple jobs for the same environment (including non-deployment jobs), you might encounter this problem, for example:
```yaml
build:service-a:
2021-03-08 18:12:59 +05:30
environment:
name: production
2021-06-08 01:23:25 +05:30
2020-06-23 00:09:42 +05:30
build:service-b:
2021-03-08 18:12:59 +05:30
environment:
name: production
2020-06-23 00:09:42 +05:30
```
2023-01-13 00:05:48 +05:30
The [Prevent outdated deployment jobs ](../pipelines/settings.md#prevent-outdated-deployment-jobs ) might
2021-03-08 18:12:59 +05:30
not work well with this configuration, and must be disabled.