Updated document structure

This commit is contained in:
Neil Lathwood
2015-01-10 00:10:51 +00:00
parent 03534ee054
commit 91e40a91ce
23 changed files with 1074 additions and 240 deletions

View File

@@ -0,0 +1,37 @@
Agent setup
-----------
To gather data from remote systems you can use LibreNMS in combination with check_mk (included in the scripts directory).
On each of the hosts you would like to use the agent on then you need to do the following:
* Copy the `check_mk_agent` script into `/usr/bin` and make it executable.
```shell
cp scripts/check_mk_agent /usr/bin/check_mk_agent
chmod +x /usr/bin/check_mk_agent
```
* Copy the xinetd config file into place.
```shell
cp scripts/check_mk_xinetd /etc/xinetd.d/check_mk
```
* Create the relevant directories.
```shell
mkdir -p /usr/lib/check_mk_agent/plugins /usr/lib/check_mk_agent/local
```
* Copy each of the scripts from `scripts/agent-local/` into `/usr/lib/check_mk_agent/local`
* And restart xinetd.
```shell
/etc/init.d/xinetd restart
```
* Login to the LibreNMS web interface and edit the device you want to monitor. Under the modules section, ensure that unix-agent is enabled.
* Then under Applications, enable the apps that you plan to monitor.
* Wait, in around 10 minutes you should start seeing data in your graphs under Apps for the device.

167
doc/Extensions/Alerting.md Normal file
View File

@@ -0,0 +1,167 @@
Table of Content:
- [About](#about)
- [Rules](#rules)
- [Syntax](#rules-syntax)
- [Examples](#rules-examples)
- [Templates](#templates)
- [Syntax](#templates-syntax)
- [Examples](#templates-examples)
- [Transports](#transports)
- [E-Mail](#transports-email)
- [API](#transports-api)
- [Nagios-Compatible](#transports-nagios)
- [IRC](#transports-irc)
# <a name="about">About</a>
LibreNMS includes a highly customizable alerting system.
The system requires a set of user-defined rules to evaluate the situation of each device, port, service or any other entity.
This document only covers the usage of it. See the [DEVELOPMENT.md](https://github.com/f0o/glowing-tyrion/blob/master/DEVELOPMENT.md) for code-documentation.
# <a name="rules">Rules</a>
Rules are defined using a logical language.
The GUI provides a simple way of creating basic as well as complex Rules in a self-describing manner.
More complex rules can be written manually.
## <a name="rules-syntax">Syntax</a>
Rules must consist of at least 3 elements: An __Entity__, a __Condition__ and a __Value__.
Rules can contain braces and __Glues__.
__Entities__ are provided as `%`-Noted pair of Table and Field. For Example: `%ports.ifOperStatus`.
__Conditions__ can be any of:
- Equals `=`
- Not Equals `!=`
- Matches `~`
- Not Matches `!~`
- Greater `>`
- Greater or Equal `>=`
- Smaller `<`
- Smaller or Equal `<=`
__Values__ can be Entities or any single-quoted data.
__Glues__ can be either `&&` for `AND` or `||` for `OR`.
__Note__: The difference between `Equals` and `Matches` (and it's negation) is that `Equals` does a strict comparison and `Matches` allows the usage of the placeholder `@`. The placeholder `@` is comparable with `.*` in RegExp.
Arithmetics are allowed as well.
## <a name="rules-examples">Examples</a>
Alert when:
- Device goes down: `%devices.status != '1'`
- Any port changes: `%ports.ifOperStatus != 'up'`
- Root-directory gets too full: `%storage.storage_descr = '/' && %storage.storage_perc >= '75'`
- Any storage gets fuller than the 'warning': `%storage.storage_perc >= %storage_perc_warn`
# <a name="templates">Templates</a>
Templates can be assigned to a single or a group of rules.
They can contain any kind of text.
The template-parser understands `if` and `foreach` controls and replaces certain placeholders with information gathered about the alert.
## <a name="templates-syntax">Syntax</a>
Controls:
- if-else (Else can be omitted):
`{if %placeholder == 'value'}Some Text{else}Other Text{/if}`
- foreach-loop:
`{foreach %placeholder}Key: %key<br/>Value: %value{/foreach}`
__Limitations__: Currently it is not possible to have nested `if` controls, so `if` inside an `if`. It is also not possible to have an `if` inside a `foreach` control. These limitations are going to be resolved in (near?) future.
Placeholders:
- Hostname of the Device: `%hostname`
- Title for the Alert: `%title`
- Time Elapsed, Only available on recovery (`%state == 0`): `%elapsed`
- Alert-ID: `%id`
- Unique-ID: `%uid`
- Faults, Only available on alert (`%state == 1`), must be iterated in a foreach: `%faults`
- State: `%state`
- Severity: `%severity`
- Rule: `%rule`
- Timestamp: `%timestamp`
- Contacts, must be iterated in a foreach, `%key` holds email and `%value` holds name: `%contacts`
## <a name="templates-examples">Examples</a>
Default Template:
```text
%title\r\n
Severity: %severity\r\n
{if %state == 0}Time elapsed: %elapsed\r\n{/if}
Timestamp: %timestamp\r\n
Unique-ID: %uid\r\n
Rule: %rule\r\n
{if %faults}Faults:\r\n
{foreach %faults} #%key: %value\r\n{/foreach}{/if}
Alert sent to: {foreach %contacts}%value <%key> {/foreach}
```
# <a name="transports">Transports</a>
Transports are located within `$config['install_dir']/includes/alerts/transports.*.php` and defined as well as configured via `$config['alert']['transports']['Example'] = 'Some Options'`.
Contacts will be gathered automatically and passed to the configured transports.
The contacts will always include the `SysContact` defined in the Device's SNMP configuration and also every LibreNMS-User that has at least `read`-permissions on the entity that is to be alerted.
At the moment LibreNMS only supports Port or Device permissions.
To include users that have `Global-Read` or `Administrator` permissions it is required to add these additions to the `config.php` respectively:
```php
$config['alert']['globals'] = true; //Include Global-Read into alert-contacts
$config['alert']['admins'] = true; //Include Adminstrators into alert-contacts
```
## <a name="transports-email">E-Mail</a>
E-Mail transport is enabled with adding the following to your `config.php`:
```php
$config['alert']['transports']['mail'] = true;
```
The E-Mail transports uses the same email-configuration like the rest of LibreNMS.
As a small reminder, here is it's configuration directives including defaults:
```php
$config['email_backend'] = 'mail'; // Mail backend. Allowed: "mail" (PHP's built-in), "sendmail", "smtp".
$config['email_from'] = NULL; // Mail from. Default: "ProjectName" <projectid@`hostname`>
$config['email_user'] = $config['project_id'];
$config['email_sendmail_path'] = '/usr/sbin/sendmail'; // The location of the sendmail program.
$config['email_smtp_host'] = 'localhost'; // Outgoing SMTP server name.
$config['email_smtp_port'] = 25; // The port to connect.
$config['email_smtp_timeout'] = 10; // SMTP connection timeout in seconds.
$config['email_smtp_secure'] = NULL; // Enable encryption. Use 'tls' or 'ssl'
$config['email_smtp_auth'] = FALSE; // Whether or not to use SMTP authentication.
$config['email_smtp_username'] = NULL; // SMTP username.
$config['email_smtp_password'] = NULL; // Password for SMTP authentication.
```
## <a name="transports-api">API</a>
API transports definitions are a bit more complex than the E-Mail configuration.
The basis for configuration is `$config['alert']['transports']['api'][METHOD]` where `METHOD` can be `get`,`post` or `put`.
This basis has to contain an array with URLs of each API to call.
The URL can have the same placeholders as defined in the [Template-Syntax](#templates-syntax).
If the `METHOD` is `get`, all placeholders will be URL-Encoded.
The API transport uses cURL to call the APIs, therefore you might need to install `php5-curl` or similar in order to make it work.
__Note__: it is highly recommended to define own [Templates](#templates) when you want to use the API transport. The default template might exceed URL-length for GET requests and therefore cause all sorts of errors.
Example:
```php
$config['alert']['transports']['api']['get'][] = "https://api.thirdparti.es/issue?apikey=abcdefg&subject=%title";
```
## <a name="transports-nagios">Nagios Compatible</a>
The nagios transport will feed a FIFO at the defined location with the same format that nagios would.
This allows you to use other Alerting-Systems to work with LibreNMS, for example [Flapjack](http://flapjack.io).
```php
$config['alert']['transports']['nagios'] = "/path/to/my.fifo"; //Flapjack expects it to be at '/var/cache/nagios3/event_stream.fifo'
```
## <a name="transports-irc">IRC</a>
The IRC transports only works together with the LibreNMS IRC-Bot.
Configuration of the LibreNMS IRC-Bot is described [here](https://github.com/librenms/librenms/blob/master/doc/IRC-Bot.md).
```php
$config['alert']['transports']['irc'] = true;
```

View File

@@ -0,0 +1,18 @@
# Billing Module
To enable and use the billing module you need to perform the following steps:
Edit `config.php` and add (or enable) the following line near the end of the config
```php
$config['enable_billing'] = 1; # Enable Billing
```
Edit `/etc/cron.d/librenms` and add the following:
```bash
*/5 * * * * root /opt/librenms/poll-billing.php >> /dev/null 2>&1
01 * * * * root /opt/librenms/billing-calculate.php >> /dev/null 2>&1
```
Create billing graphs as required.

View File

@@ -0,0 +1,23 @@
Currently, the email alerts needs to be set up in the config. If you want to enable it, paste this in your config and change it:
```php
// Mailer backend Settings
$config['email_backend'] = 'mail'; // Mail backend. Allowed: "mail" (PHP's built-in), "sendmail", "smtp".
$config['email_from'] = NULL; // Mail from. Default: "ProjectName" <projectid@`hostname`>
$config['email_user'] = $config['project_id'];
$config['email_sendmail_path'] = '/usr/sbin/sendmail'; // The location of the sendmail program.
$config['email_smtp_host'] = 'localhost'; // Outgoing SMTP server name.
$config['email_smtp_port'] = 25; // The port to connect.
$config['email_smtp_timeout'] = 10; // SMTP connection timeout in seconds.
$config['email_smtp_secure'] = NULL; // Enable encryption. Use 'tls' or 'ssl'
$config['email_smtp_auth'] = FALSE; // Whether or not to use SMTP authentication.
$config['email_smtp_username'] = NULL; // SMTP username.
$config['email_smtp_password'] = NULL; // Password for SMTP authentication.
// Alerting Settings
$config['alerts']['email']['default'] = 'sendto@somewhere.com'; // Default alert recipient
$config['alerts']['email']['default_only'] = FALSE; // Only use default recipient
$config['alerts']['email']['enable'] = TRUE; // Enable email alerts
$config['alerts']['bgp']['whitelist'] = NULL; // Populate as an array() with ASNs to alert on.
$config['alerts']['port']['ifdown'] = FALSE; // Generate alerts for ports that go down
```

View File

@@ -0,0 +1,80 @@
# Quick Guide
Okay this is a very quick walk-through in writing own `commands` for the IRC-Bot.
First of all, create a file in `includes/ircbot`, the file-name should be in this format: `command.inc.php`.
When editing the file, do not open nor close PHP-tags.
Any variable you assign will be discarded as soon as your command returns.
Some variables, specially all listed under `$this->`, have special meanings or effects.
Before a command is executed, the IRC-Bot ensures that the MySQL-Socket is working, that `$this->user` points to the right user and that the user is authenticated.
Below you will find a table with related functions and attributes.
You can chain-load any built-in command by calling `$this->_command("My Parameters")`.
You cannot chain-load external commands.
To enable your command, edit your `config.php` and add something like this:
```php
...
$config['irc_external'][] = "mycommand";
...
```
See: [Example](#example)
# Functions and Attributes
... that are accessible from within an extension
### <a name="glob.func">Functions</a>
Function( (Type) $Variable [= Default] [,...] ) | Returns | Description
--- | --- | ---
`$this->getChan( )` | `String` | Returns `channel` of current event.
`$this->getData( (boolean) $Block = false )` | `String/Boolean` | Returns a `line` from the IRC-Buffer if it's not matched against any other `command`. If `$Block` is `true`, wait until a suitable line is returned.
`$this->getUser( )` | `String` | Returns `nick` of current user. Not to confuse with `$this->user`!
`$this->get_user( )` | `Array` | See `$this->user` in Attributes.
`$this->irc_raw( (string) $Protocol )` | `Boolean` | Sends raw IRC-Protocol.
`$this->isAuthd( )` | `Boolean` | `true` if the user is authenticated.
`$this->joinChan( (string) $Channel )` | `Boolean` | Joins given `$Channel`.
`$this->log( (string) $Message )` | `Boolean` | Logs given `$Message` into `STDOUT`.
`$this->read( (string) $Buffer )` | `String/Boolean` | Returns a `line` from given `$Buffer` or `false` if there's nothing suitable inside the Buffer. Please use `$this->getData()` for handler-safe data retrieval.
`$this->respond( (string) $Message )` | `Boolean` | Responds to the `request` auto-detecting channel or private message.
### <a name="glob.attr">Attributes</a>
Attribute | Type | Description
--- | --- | ---
`$params` | `String` | Contains all arguments that are passed to the `.command`.
`$this->chan` | `Array` | Channels that are configured.
`$this->commands` | `Array` | Contains accessible `commands`.
`$this->config` | `Array` | Contains `$config` from `config.php`.
`$this->data` | `String` | Contains raw IRC-Protocol.
`$this->debug` | `Boolean` | Debug-Flag.
`$this->external` | `Array` | Contains loaded extra `commands`.
`$this->nick` | `String` | Bot's `nick` on the IRC.
`$this->pass` | `String` | IRC-Server's passphrase.
`$this->port` | `Int` | IRC-Sever's port-number.
`$this->server` | `String` | IRC-Server's hostname.
`$this->ssl` | `Boolean` | SSL-Flag.
`$this->tick` | `Int` | Interval to check buffers in microseconds.
`$this->user` | `Array` | Array containing details about the `user` that sent the `request`.
# <a name="example">Example!</a>
`includes/ircbot/join-ng.inc.php`
```php
if( $this->user['level'] != 10 ) {
return $this->respond("Sorry only admins can make me join.");
}
if( $this->getChan() == "#noc") {
$this->respond("Joining $params");
$this->joinChan($params);
} else {
$this->respond("Sorry, only people from #noc can make join.");
}
```
`config.php`
```php
...
$config['irc_external'][] = "join-ng";
...
```

130
doc/Extensions/IRC-Bot.md Normal file
View File

@@ -0,0 +1,130 @@
Table of Content:
- [About](#about)
- [Configuration](#config)
- [Commands](#commands)
- [Examples](#examples)
- [Extensions](#extensions)
# <a name="about">About</a>
LibreNMS has an easy to use IRC-Interface for basic tasks like viewing last log-entry, current device/port status and such.
By default the IRC-Bot will not start when executed and will return an error until at least `$config['irc_host']` and `$config['irc_port']` has been specified inside `config.php`.
If no channel has been specified with `$config['irc_chan']`, `##librenms` will be used.
The default Nick for the bot is `LibreNMS`.
The Bot will reply the same way it's being called. If you send it the commands via Query, it will respond in the Query. If you send the commands via a Channel, then it will respond in the Channel.
### <a name="config">Configuration & Defaults</a>
Option | Default-Value | Notes
--- | --- | ---
`$config['irc_alert']` | `false` | Optional; Enables Alerting-Socket. `EXPERIMENTAL`
`$config['irc_authtime']` | `3` | Optional; Defines how long in Hours an auth-session is valid.
`$config['irc_chan']` | `##librenms` | Optional; Multiple channels can be defined as Array or delimited with `,`
`$config['irc_debug']` | `false` | Optional; Enables debug output (Wall of text)
`$config['irc_external']` | | Optional; Array or `,` delimited string with commands to include from `includes/ircbot/*.inc.php`
`$config['irc_host']` | | Required; Domain or IP to connect. If it's an IPv6 Address, embed it in `[]`. (Example: `[::1]`)
`$config['irc_maxretry]` | `5` | Optional; How many connection attempts should be made before giving up
`$config['irc_nick']` | `LibreNMS` | Optional;
`$config['irc_pass']` | | Optional; This sends the IRC-PASS Sequence to IRC-Servers that require Password on Connect
`$config['irc_port']` | `6667` | Required; To enable SSL append a `+` before the Port. (Example: `+6697`)
### <a name="commands">IRC-Commands</a>
Command | Description
--- | ---
`.auth <User/Token>` | If `<user>`: Request an Auth-Token. If `<token>`: Authenticate session.
`.device <hostname>` | Prints basic information about given `hostname`.
`.down` | List hostnames that are down, if any.
`.help` | List available commands.
`.join <channel>` | Joins `<channel>` if user has admin-level.
`.listdevices` | Lists the hostnames of all known devices.
`.log [<N>]` | Prints `N` lines or last line of the eventlog.
`.port <hostname> <ifname>` | Prints Port-related informations from `ifname` on given `hostname`.
`.quit` | Disconnect from IRC and exit.
`.reload` | Reload configuration.
`.status <type>` | Prints status informations for given `type`. Type can be `devices`, `services`, `ports`. Shorthands are: `dev`,`srv`,`prt`
`.version` | Prints `$this->config['project_name_version']`.
( __/!\__ All commands are case-_insensitive_ but their arguments are case-_sensitive_)
# <a name="examples">Examples</a>
### Server examples:
Unencrypted Connection to `irc.freenode.org`:
```php
...
$config['irc_host'] = "irc.freenode.org";
$config['irc_port'] = 6667;
...
```
SSL-Encrypted Connection to `irc.freenode.org`:
```php
...
$config['irc_host'] = "irc.freenode.org";
$config['irc_port'] = "+6697";
...
```
SSL-Encrypted Connection to `irc.localdomain` with Server-Password and odd port:
```php
...
$config['irc_host'] = "irc.localdomain";
$config['irc_port'] = "+12345";
$config['irc_pass'] = "Super Secret Passphrase123";
...
```
### Channel notations:
Channels can be defined using Array-Notation like:
```php
...
$config['irc_chan'][] = "#librenms";
$config['irc_chan'][] = "#otherchan";
$config['irc_chan'][] = "#noc";
...
```
Or using a single string using `,` as delimiter between various channels:
```php
...
$config['irc_chan'] = "#librenms,#otherchan,#noc";
...
```
# <a name="extensions">Extensions?!</a>
The bot is coded in a unified way.
This makes writing extensions by far less painfull.
Simply add your `command` to the `$config['irc_external']` directive and create a file called `includes/ircbot/command.inc.php` containing your code.
The string behind the call of `.command` is passed as `$params`.
The user who requested something is accessable via `$this->user`.
Send your reply/ies via `$this->respond($string)`.
A more detailed documentation of the functions and variables available for extensions can be found at [IRC-Bot Extensions](IRC-Bot-Extensions);
Confused? Here an Echo-Example:
File: config.php
```php
...
$config['irc_external'][] = "echo";
...
```
File: includes/ircbot/echo.inc.php
```php
//Prefix everything with `You said: '...'` and return what was sent.
if( $this->user['name'] != "root" ) {
return $this->respond("You said: '".$params."'");
} else {
return $this->respond("root shouldn't be online so late!");
}
```

View File

@@ -0,0 +1,55 @@
Table of Content:
- [About](#about)
- [Setup](#setup)
- [Keywords](#keywords)
- [Type-keywords](#type-keywords)
- [Info-keywords](#info-keywords)
- [Examples](#examples)
- [Sourcecode](#source)
# <a name="about">About</a>:
Librenms can interpret, display and group certain additional information on ports.
For this a small `bash` script is supplied in `librenms/scripts` called `ifAlias`.
<a name="setup">Setup</a>:
This requires a little bit of setup on the monitored Server (Not the server running librenms!):
* Add `ifAlias` from `/path/to/librenms/scripts/` or download it from [here](#source) to the Server and make
it executeable `chmod +x /path/to/ifAlias`
* Add to `snmpd.conf` something like:
``pass .1.3.6.1.2.1.31.1.1.1.18 /path/to/ifAlias``
* Restart your `net-snmpd`
There are no changes to be made or additions to insteall for the polling librenms.
Now you can set up your [keywords](#keywords) in your `/etc/network/interfaces`
``//Add more distributions than just Debian based``
# <a name="keywords">Keywords</a>:
See [examples](#examples) for formats.
* <a name="type-keywords">Type-keywords</a>:
* `Cust` - Customer
* `Transit` - Transit link
* `Peering` - Peering link
* `Core` - Infrastructure link (non-customer)
* `Server` - Server link (non-customer)
* <a name="info-keywords">Info-keywords</a>:
* `()` contains a note
* `{}` contains *your* circuit id
* `[]` contains the service type or speed
# <a name="examples">Examples</a>:
```text
# eth3: Cust: Example Customer [10Mbit] (T1 Telco Y CCID129031) {EXAMP0001}`
# eth0: Transit: Example Provider (AS65000)`
# eth1: Core: core.router01 FastEthernet0/0 (Telco X CCID023141)`
# eth2: Peering: Peering Exchange
```
# <a name="source">Sourcecode</a>:
* https://github.com/librenms/librenms/blob/master/scripts/ifAlias

View File

@@ -0,0 +1,61 @@
# Developing for the Plugin System
This documentation will hopefully give you a basis for how to write a plugin for LibreNMS.
A test plugin is available on GitHib: https://github.com/laf/Test
Plugins need to be installed into html/plugins
The structure of a plugin is follows:
```
html/plugins
/PluginName
/PluginName.php
/PluginName.inc.php
```
The above structure is checked before a plugin can be installed.
All files / folder names are case sensitive and must match.
PluginName - This is a directory and needs to be named as per the plugin you are creating.
PluginName.php - This file is used to process calls into the plugin from the main LibreNMS install.
Here only functions within the class for your plugin that LibreNMS calls will be executed.
For a list of currently enabled system hooks, please see further down.
The minimum code required in this file is (replace Test with the name of your plugin):
```
<?php
class Test {
}
?>
```
PluginName.inc.php - This file is the main included file when browsing to the plugin itself.
You can use this to display / edit / remove whatever you like.
The minimum code required in this file is:
```
<?php
?>
```
### System Hooks ###
System hooks are called as functions within your plugin class, so for example to create a menu entry within the PLugin dropdown you would do:
```
public function menu() {
echo('<li><a href="plugin/p='.get_class().'">'.get_class().'</a></li>');
}
```
This would then add the name and a link to your plugin.
The following system hooks are currently available:
menu()
* This is called to build the plugin menu system and you can use this to link to your plugin (you don't have to).

View File

@@ -0,0 +1,73 @@
Table of Content:
- [About](#about)
- [Types](#types)
- [Timebased One-Time-Password (TOTP)](#totp)
- [Counterbased One-Time-Password (HOTP)](#hotp)
- [Configuration](#config)
- [Usage](#usage)
- [Google Authenticator](#usage-google)
# <a name="about">About</a>
Over the last couple of years, the primary attack vector for internet accounts has been static passwords.
Therefore static passwords are no longer suffient to protect unauthorized access to accounts.
Two Factor Authentication adds a variable part in authentication procedures.
A user is now required to supply a changing 6-digit passcode in addition to it's password to obtain access to the account.
LibreNMS has a RFC4226 conform implementation of both Time and Counter based One-Time-Passwords.
It also allows the administrator to configure a throttle time to enforce after 3 failures exceeded. Unlike RFC4226 suggestions, this throttle time will not stack on the amount of failures.
# <a name="types">Types</a>
In general, these two types do not differ in algorithmic terms.
The types only differ in the variable being used to derive the passcodes from.
The underlying HMAC-SHA1 remains the same for both types, security advantages or disadvantages of each are discussed further down.
## <a name="totp">Timebased One-Time-Password (TOTP)</a>
Like the name suggests, this type uses the current Time or a subset of it to generate the passcodes.
These passcodes solely rely on the secrecy of their Secretkey in order to provide passcodes.
An attacker only needs to guess that Secretkey and the other variable part is any given time, presumably the time upon login.
RFC4226 suggests a resynchronization attempt in case the passcode mismatches, providing the attacker a range of upto +/- 3 Minutes to create passcodes.
## <a name="hotp">Counterbased One-Time-Password (TOTP)</a>
This type uses an internal counter that needs to be in-synch with the server's counter to successfully authenticate the passcodes.
The main advantage over timebased OTP is the attacker doesnt only need to know the Secretkey but also the server's Counter in order to create valid passcodes.
RFC4226 suggests a resynchronization attempt in case the passcode mismatches, providing the attacker a range of upto +4 increments from the actual counter to create passcodes.
# <a name="config">Configuration</a>
Enable Two-Factor:
```php
$config['twofactor'] = true;
```
Set throttle-time (in secconds):
```php
$config['twofactor_lock'] = 300;
```
# <a name="usage">Usage</a>
These steps imply that TwoFactor has been enabled in your `config.php`
Create a Two-Factor key:
- Go to 'My Settings' (/preferences/)
- Choose TwoFactor type
- Click on 'Generate TwoFactor Secret Key'
- If your browser didnt reload, reload manually
- Scan provided QR or click on 'Manual' to see the Key
## <a name="usage-google">Google Authenticator</a>
__Note__: Google Authenticator only allows counterbased OTP when scanned via QR codes.
Installation guides for Google Authneticator can be found [here](https://support.google.com/accounts/answer/1066447?hl=en).
Usage:
- Create a key like described above
- Scan provided QR or click on 'Manual' and type down the Secret
- On next login, enter the passcode that the App provides