diff options
Diffstat (limited to 'doc')
26 files changed, 760 insertions, 118 deletions
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md index 87e96b71dd4..387c3fb6a5b 100644 --- a/doc/administration/high_availability/nfs.md +++ b/doc/administration/high_availability/nfs.md @@ -39,23 +39,11 @@ Our support team will not be able to assist on performance issues related to file system access. Customers and users have reported that AWS EFS does not perform well for GitLab's -use-case. There are several issues that can cause problems. For these reasons -GitLab does not recommend using EFS with GitLab. - -- EFS bases allowed IOPS on volume size. The larger the volume, the more IOPS - are allocated. For smaller volumes, users may experience decent performance - for a period of time due to 'Burst Credits'. Over a period of weeks to months - credits may run out and performance will bottom out. -- To keep "Burst Credits" available, it may be necessary to provision more space - with 'dummy data'. However, this may get expensive. -- Another option to maintain "Burst Credits" is to use FS Cache on the server so - that AWS doesn't always have to go into EFS to access files. -- For larger volumes, allocated IOPS may not be the problem. Workloads where - many small files are written in a serialized manner are not well-suited for EFS. - EBS with an NFS server on top will perform much better. - -In addition, avoid storing GitLab log files (e.g. those in `/var/log/gitlab`) -because this will also affect performance. We recommend that the log files be +use-case. Workloads where many small files are written in a serialized manner, like `git`, +are not well-suited for EFS. EBS with an NFS server on top will perform much better. + +If you do choose to use EFS, avoid storing GitLab log files (e.g. those in `/var/log/gitlab`) +there because this will also affect performance. We recommend that the log files be stored on a local volume. For more details on another person's experience with EFS, see diff --git a/doc/administration/img/raketasks/check_repos_output.png b/doc/administration/img/raketasks/check_repos_output.png Binary files differdeleted file mode 100644 index 7fda2ba0c0f..00000000000 --- a/doc/administration/img/raketasks/check_repos_output.png +++ /dev/null diff --git a/doc/administration/index.md b/doc/administration/index.md index 88190b2df5f..112d14652af 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -106,6 +106,7 @@ created in snippets, wikis, and repos. - [Gitaly](gitaly/index.md): Configuring Gitaly, GitLab's Git repository storage service. - [Default labels](../user/admin_area/labels.html): Create labels that will be automatically added to every new project. - [Restrict the use of public or internal projects](../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects): Restrict the use of visibility levels for users when they create a project or a snippet. +- [Custom project templates](https://docs.gitlab.com/ee/user/admin_area/custom_project_templates.html): Configure a set of projects to be used as custom templates when creating a new project. **[PREMIUM ONLY]** ### Repository settings diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md index 89331238ce4..752a2774bd7 100644 --- a/doc/administration/operations/fast_ssh_key_lookup.md +++ b/doc/administration/operations/fast_ssh_key_lookup.md @@ -1,3 +1,10 @@ +# Consider using SSH certificates instead of, or in addition to this + +This document describes a drop-in replacement for the +`authorized_keys` file for normal (non-deploy key) users. Consider +using [ssh certificates](ssh_certificates.md), they are even faster, +but are not is not a drop-in replacement. + # Fast lookup of authorized SSH keys in the database > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1631) in diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md index 5655b7efec6..e9cad99c4b0 100644 --- a/doc/administration/operations/index.md +++ b/doc/administration/operations/index.md @@ -14,4 +14,7 @@ that to prioritize important jobs. - [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller to restart Sidekiq. - [Unicorn](unicorn.md): Understand Unicorn and unicorn-worker-killer. -- [Speed up SSH operations](fast_ssh_key_lookup.md): Authorize SSH users via a fast, indexed lookup to the GitLab database. +- Speed up SSH operations by [Authorizing SSH users via a fast, +indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or +by [doing away with user SSH keys stored on GitLab entirely in favor +of SSH certificates](ssh_certificates.md). diff --git a/doc/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md new file mode 100644 index 00000000000..8968afba01b --- /dev/null +++ b/doc/administration/operations/ssh_certificates.md @@ -0,0 +1,165 @@ +# User lookup via OpenSSH's AuthorizedPrincipalsCommand + +> [Available in](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19911) GitLab +> Community Edition 11.2. + +GitLab's default SSH authentication requires users to upload their ssh +public keys before they can use the SSH transport. + +In centralized (e.g. corporate) environments this can be a hassle +operationally, particularly if the SSH keys are temporary keys issued +to the user, e.g. ones that expire 24 hours after issuing. + +In such setups some external automated process is needed to constantly +upload the new keys to GitLab. + +> **Warning:** OpenSSH version 6.9+ is required because that version +introduced the `AuthorizedPrincipalsCommand` configuration option. If +using CentOS 6, you can [follow these +instructions](fast_ssh_key_lookup.html#compiling-a-custom-version-of-openssh-for-centos-6) +to compile an up-to-date version. + +## Why use OpenSSH certificates? + +By using OpenSSH certificates all the information about what user on +GitLab owns the key is encoded in the key itself, and OpenSSH itself +guarantees that users can't fake this, since they'd need to have +access to the private CA signing key. + +When correctly set up, this does away with the requirement of +uploading user SSH keys to GitLab entirely. + +## Setting up SSH certificate lookup via GitLab Shell + +How to fully setup SSH certificates is outside the scope of this +document. See [OpenSSH's +PROTOCOL.certkeys](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD) +for how it works, and e.g. [RedHat's documentation about +it](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-using_openssh_certificate_authentication). + +We assume that you already have SSH certificates set up, and have +added the `TrustedUserCAKeys` of your CA to your `sshd_config`, e.g.: + +``` +TrustedUserCAKeys /etc/security/mycompany_user_ca.pub +``` + +Usually `TrustedUserCAKeys` would not be scoped under a `Match User +git` in such a setup, since it would also be used for system logins to +the GitLab server itself, but your setup may vary. If the CA is only +used for GitLab consider putting this in the `Match User git` section +(described below). + +The SSH certificates being issued by that CA **MUST** have a "key id" +corresponding to that user's username on GitLab, e.g. (some output +omitted for brevity): + +``` +$ ssh-add -L | grep cert | ssh-keygen -L -f - +(stdin):1: + Type: ssh-rsa-cert-v01@openssh.com user certificate + Public key: RSA-CERT SHA256:[...] + Signing CA: RSA SHA256:[...] + Key ID: "aearnfjord" + Serial: 8289829611021396489 + Valid: from 2018-07-18T09:49:00 to 2018-07-19T09:50:34 + Principals: + sshUsers + [...] + [...] +``` + +Technically that's not strictly true, e.g. it could be +`prod-aearnfjord` if it's a SSH certificate you'd normally log in to +servers as the `prod-aearnfjord` user, but then you must specify your +own `AuthorizedPrincipalsCommand` to do that mapping instead of using +our provided default. + +The important part is that the `AuthorizedPrincipalsCommand` must be +able to map from the "key id" to a GitLab username in some way, the +default command we ship assumes there's a 1=1 mapping between the two, +since the whole point of this is to allow us to extract a GitLab +username from the key itself, instead of relying on something like the +default public key to username mapping. + +Then, in your `sshd_config` set up `AuthorizedPrincipalsCommand` for +the `git` user. Hopefully you can use the default one shipped with +GitLab: + +``` +Match User git + AuthorizedPrincipalsCommandUser root + AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers +``` + +This command will emit output that looks something like: + +``` +command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL} +``` + +Where `{KEY_ID}` is the `%i` argument passed to the script +(e.g. `aeanfjord`), and `{PRINCIPAL}` is the principal passed to it +(e.g. `sshUsers`). + +You will need to customize the `sshUsers` part of that. It should be +some principal that's guaranteed to be part of the key for all users +who can log in to GitLab, or you must provide a list of principals, +one of which is going to be present for the user, e.g.: + +``` + [...] + AuthorizedPrincipalsCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-principals-check %i sshUsers windowsUsers +``` + +## Principals and security + +You can supply as many principals as you want, these will be turned +into multiple lines of `authorized_keys` output, as described in the +`AuthorizedPrincipalsFile` documentation in `sshd_config(5)`. + +Normally when using the `AuthorizedKeysCommand` with OpenSSH the +principal is some "group" that's allowed to log into that +server. However with GitLab it's only used to appease OpenSSH's +requirement for it, we effectively only care about the "key id" being +correct. Once that's extracted GitLab will enforce its own ACLs for +that user (e.g. what projects the user can access). + +So it's OK to e.g. be overly generous in what you accept, since if the +user e.g. has no access to GitLab at all it'll just error out with a +message about this being an invalid user. + +## Interaction with the `authorized_keys` file + +SSH certificates can be used in conjunction with the `authorized_keys` +file, and if setup as configured above the `authorized_keys` file will +still serve as a fallback. + +This is because if the `AuthorizedPrincipalsCommand` can't +authenticate the user, OpenSSH will fall back on +`~/.ssh/authorized_keys` (or the `AuthorizedKeysCommand`). + +Therefore there may still be a reason to use the ["Fast lookup of +authorized SSH keys in the database"](fast_ssh_key_lookup.html) method +in conjunction with this. Since you'll be using SSH certificates for +all your normal users, and relying on the `~/.ssh/authorized_keys` +fallback for deploy keys, if you make use of those. + +But you may find that there's no reason to do that, since all your +normal users will use the fast `AuthorizedPrincipalsCommand` path, and +only automated deployment key access will fall back on +`~/.ssh/authorized_keys`, or that you have a lot more keys for normal +users (especially if they're renewed) than you have deploy keys. + +## Other security caveats + +Users can still bypass SSH certificate authentication by manually +uploading an SSH public key to their profile, relying on the +`~/.ssh/authorized_keys` fallback to authenticate it. There's +currently no feature to prevent this, [but there's an open request for +adding it](https://gitlab.com/gitlab-org/gitlab-ce/issues/49218). + +Such a restriction can currently be hacked in by e.g. providing a +custom `AuthorizedKeysCommand` which checks if the discovered key-ID +returned from `gitlab-shell-authorized-keys-check` is a deploy key or +not (all non-deploy keys should be refused). diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md index 0c145830f02..0ca1d77f1d0 100644 --- a/doc/administration/raketasks/check.md +++ b/doc/administration/raketasks/check.md @@ -1,4 +1,4 @@ -# Check Rake Tasks +# Integrity Check Rake Task ## Repository Integrity @@ -28,14 +28,8 @@ exactly which repositories are causing the trouble. ### Check all GitLab repositories ->**Note:** -> -> - `gitlab:repo:check` has been deprecated in favor of `gitlab:git:fsck` -> - [Deprecated][ce-15931] in GitLab 10.4. -> - `gitlab:repo:check` will be removed in the future. [Removal issue][ce-41699] - This task loops through all repositories on the GitLab server and runs the -3 integrity checks described previously. +integrity check described previously. **Omnibus Installation** @@ -49,33 +43,6 @@ sudo gitlab-rake gitlab:git:fsck sudo -u git -H bundle exec rake gitlab:git:fsck RAILS_ENV=production ``` -### Check repositories for a specific user - -This task checks all repositories that a specific user has access to. This is important -because sometimes you know which user is experiencing trouble but you don't know -which project might be the cause. - -If the rake task is executed without brackets at the end, you will be prompted -to enter a username. - -**Omnibus Installation** - -```bash -sudo gitlab-rake gitlab:user:check_repos -sudo gitlab-rake gitlab:user:check_repos[<username>] -``` - -**Source Installation** - -```bash -sudo -u git -H bundle exec rake gitlab:user:check_repos RAILS_ENV=production -sudo -u git -H bundle exec rake gitlab:user:check_repos[<username>] RAILS_ENV=production -``` - -Example output: - -![gitlab:user:check_repos output](../img/raketasks/check_repos_output.png) - ## Uploaded Files Integrity Various types of files can be uploaded to a GitLab installation by users. @@ -167,5 +134,4 @@ The LDAP check Rake task will test the bind_dn and password credentials executed as part of the `gitlab:check` task, but can run independently. See [LDAP Rake Tasks - LDAP Check](ldap.md#check) for details. -[ce-15931]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15931 -[ce-41699]: https://gitlab.com/gitlab-org/gitlab-ce/issues/41699 +[git-fsck]: https://git-scm.com/docs/git-fsck diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md index 087fe729b28..88221db78f1 100644 --- a/doc/administration/repository_storage_types.md +++ b/doc/administration/repository_storage_types.md @@ -73,7 +73,7 @@ by another folder with the next 2 characters. They are both stored in a special ### How to migrate to Hashed Storage In GitLab, go to **Admin > Settings**, find the **Repository Storage** section -and select "_Create new projects using hashed storage paths_". +and select "_Use hashed storage paths for newly created and renamed projects_". To migrate your existing projects to the new storage type, check the specific [rake tasks]. diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md index 7ae4f7c1515..2902af8c782 100644 --- a/doc/administration/troubleshooting/debug.md +++ b/doc/administration/troubleshooting/debug.md @@ -77,7 +77,12 @@ and more. However, this is not enabled by default. To enable it, define the gitlab_rails['env'] = {"ENABLE_RBTRACE" => "1"} ``` -Then reconfigure the system and restart Unicorn and Sidekiq. +Then reconfigure the system and restart Unicorn and Sidekiq. To run this +in Omnibus, run as root: + +```ruby +/opt/gitlab/embedded/bin/ruby /opt/gitlab/embedded/bin/rbtrace +``` ## Common Problems diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md index 85eca403253..77e73b23021 100644 --- a/doc/administration/uploads.md +++ b/doc/administration/uploads.md @@ -142,12 +142,6 @@ These task complies with the `BATCH` environment variable to process uploads in gitlab-rake "gitlab:uploads:migrate[FileUploader, MergeRequest]" ``` - Currently this has to be executed manually and it will allow you to - migrate the existing uploads to the object storage, but all new - uploads will still be stored on the local disk. In the future - you will be given an option to define a default storage for all - new files. - --- **In installations from source:** @@ -200,12 +194,6 @@ _The uploads are stored by default in ``` - Currently this has to be executed manually and it will allow you to - migrate the existing uploads to the object storage, but all new - uploads will still be stored on the local disk. In the future - you will be given an option to define a default storage for all - new files. - [reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab" [restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab" [eep]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition Premium" diff --git a/doc/api/issues.md b/doc/api/issues.md index 92fb3e9c307..103eaa5655f 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -463,6 +463,7 @@ POST /projects/:id/issues | Attribute | Type | Required | Description | |-------------------------------------------|----------------|----------|--------------| | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `iid` | integer/string | no | The internal ID of the project's issue (requires admin or project owner rights) | | `title` | string | yes | The title of an issue | | `description` | string | no | The description of an issue | | `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. | diff --git a/doc/api/settings.md b/doc/api/settings.md index b6f2101fc7b..68fc56b1fa3 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -55,7 +55,8 @@ Example response: "ed25519_key_restriction": 0, "enforce_terms": true, "terms": "Hello world!", - "performance_bar_allowed_group_id": 42 + "performance_bar_allowed_group_id": 42, + "instance_statistics_visibility_private": false } ``` @@ -159,6 +160,7 @@ PUT /application/settings | `version_check_enabled` | boolean | no | Let GitLab inform you when an update is available. | | `enforce_terms` | boolean | no | Enforce application ToS to all users | | `terms` | text | yes (if `enforce_terms` is true) | Markdown content for the ToS | +| `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins | ```bash curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal @@ -203,6 +205,7 @@ Example response: "ed25519_key_restriction": 0, "enforce_terms": true, "terms": "Hello world!", - "performance_bar_allowed_group_id": 42 + "performance_bar_allowed_group_id": 42, + "instance_statistics_visibility_private": false } ``` diff --git a/doc/api/users.md b/doc/api/users.md index 07f9baf06d2..a8858468cab 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -440,6 +440,83 @@ GET /user } ``` +## User status + +Get the status of the currently signed in user. + +``` +GET /user/status +``` + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/user/status" +``` + +Example response: + +```json +{ + "emoji":"coffee", + "message":"I crave coffee :coffee:", + "message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>" +} +``` + +## Get the status of a user + +Get the status of a user. + +``` +GET /users/:id_or_username/status +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id_or_username` | string | yes | The id or username of the user to get a status of | + +```bash +curl "https://gitlab.example.com/users/janedoe/status" +``` + +Example response: + +```json +{ + "emoji":"coffee", + "message":"I crave coffee :coffee:", + "message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>" +} +``` + +## Set user status + +Set the status of the current user. + +``` +PUT /user/status +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `emoji` | string | no | The name of the emoji to use as status, if omitted `speech_balloon` is used. Emoji name can be one of the specified names in the [Gemojione index][gemojione-index]. | +| `message` | string | no | The message to set as a status. It can also contain emoji codes. | + +When both parameters `emoji` and `message` are empty, the status will be cleared. + +```bash +curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "emoji=coffee" --data "emoji=I crave coffee" https://gitlab.example.com/api/v4/user/status +``` + +Example responses + +```json +{ + "emoji":"coffee", + "message":"I crave coffee", + "message_html": "I crave coffee" +} +``` + ## List user projects Please refer to the [List of user projects ](projects.md#list-user-projects). @@ -1167,3 +1244,5 @@ Example response: ``` Please note that `last_activity_at` is deprecated, please use `last_activity_on`. + +[gemojione-index]: https://github.com/jonathanwiesel/gemojione/blob/master/config/index.json diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md index a433cd5a5dd..087b317ab73 100644 --- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md +++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md @@ -46,7 +46,7 @@ This project has three jobs: ## Store API keys -You'll need to create two variables in `Project > Variables`: +You'll need to create two variables in `Settings > CI/CD > Variables` on your GitLab project settings: 1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app, 2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app. diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index d95f8c7c8cc..95d705d3a3d 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -962,8 +962,8 @@ the binaries directory: ```yaml job: - artifacts: - name: "$CI_COMMIT_REF_NAME" + artifacts: + name: "$CI_COMMIT_REF_NAME" paths: - binaries/ ``` diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md index 1320efaf767..da836a0e82e 100644 --- a/doc/development/fe_guide/performance.md +++ b/doc/development/fe_guide/performance.md @@ -15,7 +15,7 @@ Use the following rules when creating realtime solutions. Use that as your polling interval. This way it is [easy for system administrators to change the polling rate](../../administration/polling.md). A `Poll-Interval: -1` means you should disable polling, and this must be implemented. -1. A response with HTTP status `4XX` or `5XX` should disable polling as well. +1. A response with HTTP status different from 2XX should disable polling as well. 1. Use a common library for polling. 1. Poll on active tabs only. Please use [Visibility](https://github.com/ai/visibilityjs). 1. Use regular polling intervals, do not use backoff polling, or jitter, as the interval will be @@ -25,15 +25,15 @@ controlled by the server. ### Lazy Loading Images -To improve the time to first render we are using lazy loading for images. This works by setting -the actual image source on the `data-src` attribute. After the HTML is rendered and JavaScript is loaded, +To improve the time to first render we are using lazy loading for images. This works by setting +the actual image source on the `data-src` attribute. After the HTML is rendered and JavaScript is loaded, the value of `data-src` will be moved to `src` automatically if the image is in the current viewport. * Prepare images in HTML for lazy loading by renaming the `src` attribute to `data-src` AND adding the class `lazy` * If you are using the Rails `image_tag` helper, all images will be lazy-loaded by default unless `lazy: false` is provided. If you are asynchronously adding content which contains lazy images then you need to call the function -`gl.lazyLoader.searchLazyImages()` which will search for lazy images and load them if needed. +`gl.lazyLoader.searchLazyImages()` which will search for lazy images and load them if needed. But in general it should be handled automatically through a `MutationObserver` in the lazy loading function. ### Animations @@ -97,19 +97,19 @@ bundle and included on the page. ```javascript import initMyWidget from './my_widget'; - + document.addEventListener('DOMContentLoaded', () => { initMyWidget(); }); ``` -- **Supporting Module Placement:** +- **Supporting Module Placement:** - If a class or a module is _specific to a particular route_, try to locate it close to the entry point it will be used. For instance, if `my_widget.js` is only imported within `pages/widget/show/index.js`, you should place the module at `pages/widget/show/my_widget.js` and import it with a relative path (e.g. `import initMyWidget from './my_widget';`). - + - If a class or module is _used by multiple routes_, place it within a shared directory at the closest common parent directory for the entry points that import it. For example, if `my_widget.js` is imported within diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md index ca8ebcdc984..ad5f6b2ecf6 100644 --- a/doc/development/i18n/proofreader.md +++ b/doc/development/i18n/proofreader.md @@ -15,6 +15,7 @@ are very appreciative of the work done by translators and proofreaders! - Chinese Traditional, Hong Kong - Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve) - Dutch + - Emily Hendle - [GitLab](https://gitlab.com/pundachan), [Crowdin](https://crowdin.com/profile/pandachan) - Esperanto - French - Davy Defaud - [GitLab](https://gitlab.com/DevDef), [Crowdin](https://crowdin.com/profile/DevDef) diff --git a/doc/development/performance.md b/doc/development/performance.md index c4162a05b77..6b4cb6d72d1 100644 --- a/doc/development/performance.md +++ b/doc/development/performance.md @@ -347,13 +347,7 @@ def expire_first_branch_cache end ``` -## Anti-Patterns - -This is a collection of [anti-patterns][anti-pattern] that should be avoided -unless these changes have a measurable, significant and positive impact on -production environments. - -### String Freezing +## String Freezing In recent Ruby versions calling `freeze` on a String leads to it being allocated only once and re-used. For example, on Ruby 2.3 this will only allocate the @@ -365,17 +359,38 @@ only once and re-used. For example, on Ruby 2.3 this will only allocate the end ``` -Blindly adding a `.freeze` call to every String is an anti-pattern that should -be avoided unless one can prove (using production data) the call actually has a -positive impact on performance. +Depending on the size of the String and how frequently it would be allocated +(before the `.freeze` call was added), this _may_ make things faster, but +there's no guarantee it will. + +Strings will be frozen by default in Ruby 3.0. To prepare our code base for +this eventuality, it's a good practice to add the following header to all +Ruby files: + +```ruby +# frozen_string_literal: true +``` + +This may cause test failures in the code that expects to be able to manipulate +strings. Instead of using `dup`, use the unary plus to get an unfrozen string: + +```ruby +test = +"hello" +test += " world" +``` + +## Anti-Patterns -This feature of Ruby wasn't really meant to make things faster directly, instead -it was meant to reduce the number of allocations. Depending on the size of the -String and how frequently it would be allocated (before the `.freeze` call was -added), this _may_ make things faster, but there's no guarantee it will. +This is a collection of [anti-patterns][anti-pattern] that should be avoided +unless these changes have a measurable, significant and positive impact on +production environments. -Another common flavour of this is to not only freeze a String, but also assign -it to a constant, for example: +### Moving Allocations to Constants + +Storing an object as a constant so you only allocate it once _may_ improve +performance, but there's no guarantee this will. Looking up constants has an +impact on runtime performance, and as such, using a constant instead of +referencing an object directly may even slow code down. For example: ```ruby SOME_CONSTANT = 'foo'.freeze @@ -393,13 +408,6 @@ there's nothing stopping somebody from doing this elsewhere in the code: SOME_CONSTANT = 'bar' ``` -### Moving Allocations to Constants - -Storing an object as a constant so you only allocate it once _may_ improve -performance, but there's no guarantee this will. Looking up constants has an -impact on runtime performance, and as such, using a constant instead of -referencing an object directly may even slow code down. - [#15607]: https://gitlab.com/gitlab-org/gitlab-ce/issues/15607 [yorickpeterse]: https://gitlab.com/yorickpeterse [anti-pattern]: https://en.wikipedia.org/wiki/Anti-pattern diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index dd8d95a3bca..2517908e5b1 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -43,7 +43,7 @@ When you create a new repo locally, instead of going to GitLab to manually create a new project and then push the repo, you can directly push it to GitLab to create the new project, all without leaving your terminal. If you have access to that -namespace, we will automatically create a new project under that GitLab namespace with its +namespace, we will automatically create a new project under that GitLab namespace with its visibility set to Private by default (you can later change it in the [project's settings](../public_access/public_access.md#how-to-change-project-visibility)). This can be done by using either SSH or HTTP: diff --git a/doc/install/installation.md b/doc/install/installation.md index 8c7f80fd8e8..ea01d88d85f 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -12,7 +12,7 @@ Since installations from source don't have Runit, Sidekiq can't be terminated an ## Select Version to Install -Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-1-stable`). +Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-2-stable`). You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar). If the highest number stable branch is unclear please check the [GitLab Blog](https://about.gitlab.com/blog/) for installation guide links by version. @@ -300,9 +300,9 @@ sudo usermod -aG redis git ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-1-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-2-stable gitlab -**Note:** You can change `11-1-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `11-2-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md index cf891cd90ad..e2eb342361a 100644 --- a/doc/raketasks/cleanup.md +++ b/doc/raketasks/cleanup.md @@ -22,3 +22,34 @@ sudo gitlab-rake gitlab:cleanup:repos # installation from source bundle exec rake gitlab:cleanup:repos RAILS_ENV=production ``` + +Clean up local project upload files if they don't exist in GitLab database. The +task attempts to fix the file if it can find its project, otherwise it moves the +file to a lost and found directory. + +``` +# omnibus-gitlab +sudo gitlab-rake gitlab:cleanup:project_uploads + +# installation from source +bundle exec rake gitlab:cleanup:project_uploads RAILS_ENV=production +``` + +Example output: + +``` +$ sudo gitlab-rake gitlab:cleanup:project_uploads +I, [2018-07-27T12:08:27.671559 #89817] INFO -- : Looking for orphaned project uploads to clean up. Dry run... +D, [2018-07-27T12:08:28.293568 #89817] DEBUG -- : Processing batch of 500 project upload file paths, starting with /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out +I, [2018-07-27T12:08:28.689869 #89817] INFO -- : Can move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/test.out +I, [2018-07-27T12:08:28.755624 #89817] INFO -- : Can fix /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/qux/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt +I, [2018-07-27T12:08:28.760257 #89817] INFO -- : Can move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png +I, [2018-07-27T12:08:28.764470 #89817] INFO -- : To cleanup these files run this command with DRY_RUN=false + +$ sudo gitlab-rake gitlab:cleanup:project_uploads DRY_RUN=false +I, [2018-07-27T12:08:32.944414 #89936] INFO -- : Looking for orphaned project uploads to clean up... +D, [2018-07-27T12:08:33.293568 #89817] DEBUG -- : Processing batch of 500 project upload file paths, starting with /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out +I, [2018-07-27T12:08:33.689869 #89817] INFO -- : Did move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/test.out -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/test.out +I, [2018-07-27T12:08:33.755624 #89817] INFO -- : Did fix /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/qux/foo/bar/89a0f7b0b97008a4a18cedccfdcd93fb/foo.txt +I, [2018-07-27T12:08:33.760257 #89817] INFO -- : Did move to lost and found /opt/gitlab/embedded/service/gitlab-rails/public/uploads/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png -> /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/project-lost-found/foo/bar/1dd6f0f7eefd2acc4c2233f89a0f7b0b/image.png +```
\ No newline at end of file diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md index dc045961ed7..8f7bb8636c5 100644 --- a/doc/university/high-availability/aws/README.md +++ b/doc/university/high-availability/aws/README.md @@ -2,10 +2,8 @@ comments: false --- -DANGER: This guide exists for reference of how an AWS deployment could work. -We are currently seeing very slow EFS access performance which causes GitLab to -be 5-10x slower than using NFS or Local disk. We _do not_ recommend follow this -guide at this time. +> **Note**: We **do not** recommend using the AWS Elastic File System (EFS), as it can result +in [significantly degraded performance](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/administration/high_availability/nfs.md#aws-elastic-file-system). # High Availability on AWS diff --git a/doc/update/11.1-to-11.2.md b/doc/update/11.1-to-11.2.md new file mode 100644 index 00000000000..3edc7e6923e --- /dev/null +++ b/doc/update/11.1-to-11.2.md @@ -0,0 +1,378 @@ +--- +comments: false +--- + +# From 11.1 to 11.2 + +Make sure you view this update guide from the branch (version) of GitLab you would +like to install (e.g., `11-2-stable`. You can select the branch in the version +dropdown at the top left corner of GitLab (below the menu bar). + +If the highest number stable branch is unclear please check the +[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation +guide links by version. + +### 1. Stop server + +```bash +sudo service gitlab stop +``` + +### 2. Backup + +NOTE: If you installed GitLab from source, make sure `rsync` is installed. + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +### 3. Update Ruby + +NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be +sure to upgrade your interpreter if necessary. + +You can check which version you are running with `ruby -v`. + +Download Ruby and compile it: + +```bash +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz +echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz +cd ruby-2.4.4 + +./configure --disable-install-rdoc +make +sudo make install +``` + +Install Bundler: + +```bash +sudo gem install bundler --no-ri --no-rdoc +``` + +### 4. Update Node + +GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets. +This requires a minimum version of node v6.0.0. + +You can check which version you are running with `node -v`. If you are running +a version older than `v6.0.0` you will need to update to a newer version. You +can find instructions to install from community maintained packages or compile +from source at the nodejs.org website. + +<https://nodejs.org/en/download/> + +GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript +dependencies. + +```bash +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn +``` + +More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). + +### 5. Update Go + +NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go +1.5.x through 1.8.x. Be sure to upgrade your installation if necessary. + +You can check which version you are running with `go version`. + +Download and install Go: + +```bash +# Remove former Go installation folder +sudo rm -rf /usr/local/go + +curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz +echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz +sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ +rm go1.10.3.linux-amd64.tar.gz +``` + +### 6. Get latest code + +```bash +cd /home/git/gitlab + +sudo -u git -H git fetch --all --prune +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically +sudo -u git -H git checkout -- locale +``` + +For GitLab Community Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 11-2-stable +``` + +OR + +For GitLab Enterprise Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 11-2-stable-ee +``` + +### 7. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell + +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION) +sudo -u git -H bin/compile +``` + +### 8. Update gitlab-workhorse + +Install and compile gitlab-workhorse. GitLab-Workhorse uses +[GNU Make](https://www.gnu.org/software/make/). +If you are not using Linux you may have to run `gmake` instead of +`make` below. + +```bash +cd /home/git/gitlab-workhorse + +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION) +sudo -u git -H make +``` + +### 9. Update Gitaly + +#### New Gitaly configuration options required + +In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`. + +```shell +echo ' +[gitaly-ruby] +dir = "/home/git/gitaly/ruby" + +[gitlab-shell] +dir = "/home/git/gitlab-shell" +' | sudo -u git tee -a /home/git/gitaly/config.toml +``` + +#### Check Gitaly configuration + +Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly +configuration file may contain syntax errors. The block name +`[[storages]]`, which may occur more than once in your `config.toml` +file, should be `[[storage]]` instead. + +```shell +sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml +``` + +#### Compile Gitaly + +```shell +cd /home/git/gitaly +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION) +sudo -u git -H make +``` + +### 10. Update gitlab-pages + +#### Only needed if you use GitLab Pages. + +Install and compile gitlab-pages. GitLab-Pages uses +[GNU Make](https://www.gnu.org/software/make/). +If you are not using Linux you may have to run `gmake` instead of +`make` below. + +```bash +cd /home/git/gitlab-pages + +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION) +sudo -u git -H make +``` + +### 11. Update MySQL permissions + +If you are using MySQL you need to grant the GitLab user the necessary +permissions on the database: + +```bash +mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';" +``` + +If you use MySQL with replication, or just have MySQL configured with binary logging, +you will need to also run the following on all of your MySQL servers: + +```bash +mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;" +``` + +You can make this setting permanent by adding it to your `my.cnf`: + +``` +log_bin_trust_function_creators=1 +``` + +### 12. Update configuration files + +#### New configuration options for `gitlab.yml` + +There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`: + +```sh +cd /home/git/gitlab + +git diff origin/11-1-stable:config/gitlab.yml.example origin/11-2-stable:config/gitlab.yml.example +``` + +#### Nginx configuration + +Ensure you're still up-to-date with the latest NGINX configuration changes: + +```sh +cd /home/git/gitlab + +# For HTTPS configurations +git diff origin/11-1-stable:lib/support/nginx/gitlab-ssl origin/11-2-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/11-1-stable:lib/support/nginx/gitlab origin/11-2-stable:lib/support/nginx/gitlab +``` + +If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx +configuration as GitLab application no longer handles setting it. + +If you are using Apache instead of NGINX please see the updated [Apache templates]. +Also note that because Apache does not support upstreams behind Unix sockets you +will need to let gitlab-workhorse listen on a TCP port. You can do this +via [/etc/default/gitlab]. + +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/lib/support/init.d/gitlab.default.example#L38 + +#### SMTP configuration + +If you're installing from source and use SMTP to deliver mail, you will need to add the following line +to config/initializers/smtp_settings.rb: + +```ruby +ActionMailer::Base.delivery_method = :smtp +``` + +See [smtp_settings.rb.sample] as an example. + +[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/config/initializers/smtp_settings.rb.sample#L13 + +#### Init script + +There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`: + +```sh +cd /home/git/gitlab + +git diff origin/11-1-stable:lib/support/init.d/gitlab.default.example origin/11-2-stable:lib/support/init.d/gitlab.default.example +``` + +Ensure you're still up-to-date with the latest init script changes: + +```bash +cd /home/git/gitlab + +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +For Ubuntu 16.04.1 LTS: + +```bash +sudo systemctl daemon-reload +``` + +### 13. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL installations (note: the line below states '--without postgres') +sudo -u git -H bundle install --without postgres development test --deployment + +# PostgreSQL installations (note: the line below states '--without mysql') +sudo -u git -H bundle install --without mysql development test --deployment + +# Optional: clean up old gems +sudo -u git -H bundle clean + +# Run database migrations +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production + +# Compile GetText PO files + +sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production + +# Update node dependencies and recompile assets +sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production + +# Clean up cache +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +``` + +**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md). + +### 14. Start application + +```bash +sudo service gitlab start +sudo service nginx restart +``` + +### 15. Check application status + +Check if GitLab and its environment are configured correctly: + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +To make sure you didn't miss anything run a more thorough check: + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +``` + +If all items are green, then congratulations, the upgrade is complete! + +## Things went south? Revert to previous version (11.1) + +### 1. Revert the code to the previous version + +Follow the [upgrade guide from 11.0 to 11.1](11.0-to-11.1.md), except for the +database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above. + +[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/config/gitlab.yml.example +[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-2-stable/lib/support/init.d/gitlab.default.example diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index e1857ce99c6..a4f17746b69 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -92,18 +92,28 @@ sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly]" RAILS_ cd /home/git/gitlab-shell sudo -u git -H git fetch --all --tags -sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` -b v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION) -b v$(</home/git/gitlab/GITLAB_SHELL_VERSION) sudo -u git -H sh -c 'if [ -x bin/compile ]; then bin/compile; fi' ``` -### 7. Start application +### 7. Update gitlab-pages to the corresponding version (skip if not using pages) + +```bash +cd /home/git/gitlab-pages + +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION) +sudo -u git -H make +``` + +### 8. Start application ```bash sudo service gitlab start sudo service nginx restart ``` -### 8. Check application status +### 9. Check application status Check if GitLab and its environment are configured correctly: diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md index 20d3f2d96f4..1b676bfb383 100644 --- a/doc/user/admin_area/monitoring/health_check.md +++ b/doc/user/admin_area/monitoring/health_check.md @@ -20,14 +20,24 @@ To access monitoring resources, the client IP needs to be included in a whitelis [Read how to add IPs to a whitelist for the monitoring endpoints][admin]. -## Using the endpoint +## Using the endpoints With default whitelist settings, the probes can be accessed from localhost: +- `http://localhost/-/health` - `http://localhost/-/readiness` - `http://localhost/-/liveness` -which will then provide a report of system health in JSON format. + +The first endpoint, `/-/health/`, only checks whether the application server is running. It does +-not verify the database or other services are running. A successful response will return +a 200 status code with the following message: + +``` +GitLab OK +``` + +The readiness and liveness probes will provide a report of system health in JSON format. Readiness example output: diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md index d3a2a7dcd14..e25e1e19b13 100644 --- a/doc/user/profile/account/two_factor_authentication.md +++ b/doc/user/profile/account/two_factor_authentication.md @@ -88,7 +88,7 @@ storage in a safe place. **Each code can be used only once** to log in to your account. If you lose the recovery codes or just want to generate new ones, you can do so -from the **Profile settings ➔ Account** page where you first enabled 2FA. +[using SSH](#generate-new-recovery-codes-using-ssh). ## Logging in with 2FA Enabled |