1 - Overview

What is Falco Talon?

What is the Falco Talon project?

Falco Talon is a Response Engine for managing threats in Kubernetes clusters. It enhances the solutions proposed by the Falco community with a no-code tailor-made solution. With easy rules, you can react to events from Falco in milliseconds.

Why having created Falco Talon?

Over the years, the Falco community proposed different methods to react to the Falco Events, what we call a response engine. All these methods rely on a 3rd party FaaS (Function as a Service) and come with drawbacks:

  • all actions must be developped by the users to manage:
    • the errors
    • the Falco event format
    • the authentication
    • the K8s SDK complexity
    • the security
    • the upgrades of the deps
  • latency
  • complexity to manage sequential actions
  • intrication between the function and its configuration

This is why we started to develop a custom solution specifically built for Falco: Falco Talon.

  • Tailor made for the Falco events
  • No-code implementation for end-users
  • UX close to Falco with the rules (yaml files with append, override mechanisms)
  • Allow to set up sequential actions to run
  • Structured logs (with a trace id)
  • An official Helm chart for the deployment in K8s

The match for the rule can be based on the:

  • Falco rule name (=)
  • priority (=, >=)
  • tags (=)
  • output fields (=, !=)

What is it good for?:

  • React in real-time to the Falco Events
  • Allow fine granularity to match the events to react to
  • Responding to default rules with specific overrides

What is it not good for?:

  • Complex reaction worflows with conditions between the steps

What is it not yet good for?

See this issue on Github to know more about the upcoming features.

Where should I go next?

Start by learning the Concepts.

2 - Concepts

Understand the concepts of Falco Talon

Why we created Talon

  • Custom-designed for immediate response to Falco events.
  • Implement response actions without coding.
  • User experience aligned with Falco, utilizing YAML for rule customization.
  • Enables configuration of action sequences triggered by Falco rules.
  • Provides structured logging complete with trace identification.
  • Simplified deployment through Helm charts.
  • Actions can be triggered on the below Falco criteria matches:
    • rule name (=)
    • priority (=, >=)
    • tags (=)
    • output fields (=, !=)

Architecture

Falco Talon can receive the events from Falco or Falcosidekick:

┌──────────┐      ┌───────────────┐      ┌─────────────┐
│  Falco   ├──────► Falcosidekick ├──────► Falco Talon │
└──────────┘      └───────────────┘      └─────────────┘
or
┌──────────┐      ┌─────────────┐
│  Falco   ├──────► Falco Talon │
└──────────┘      └─────────────┘

Keywords

Event

Represents a possible threat or suspicious action detected by Falco and is sent to the outputs.

Rule

The rule define the criteria for linking the events with the actions to run.

See here to know more.

Action

Each rule can sequentially run actions, each action refers to an actionner to know what to do.

See here to know more.

Actionner

It defines what the action will do.

For example:

See here to know more.

Notifier

It defines what outputs to notify with the result of the action.

See here to know more.

Deduplication

Falco Talon is able to de-duplicate the received events from Falco. It may happen Falco triggers the same rule multiple times for the same origin action (eg: change of thread.id) and Falco Talon can de-duplicate these events to avoid to run several times the same action.

The de-deduplication function can also work in a multi pods in Kubernetes context, Falco Talon will create a lease to elect a leader that will aggregate all events from the other Falco Talon pods. In case of any issue, a new leader is automatically elected.

See here for the settings.

3 - Configuration

Configuration file

Configuration

The static configuration of Falco Talon is set with a .yaml file (default: ./config.yaml) or with environment variables.

SettingEnv varDefaultDescription
listen_addressLISTEN_ADDRESS0.0.0.0Listten Address
listen_portLISTEN_PORT2803Listten Port
rules_filesRULES_FILESn/aFile with rules
watch_rulesWATCH_RULEStrueReload rules if they change
print_all_eventsPRINT_ALL_EVENTStruePrint in logs all received events, not only those which matches
kubeconfigKUBECONFIGn/aKube config file, only if Falco Talon runs outside Kubernetes
log_formatLOG_FORMATcolorLog Format: text, color, json
deduplication_leader_leaseDEDUPLICATION_LEADER_LEASEtrueIn k8s only, create a lease for the leader election, used for the deduplication
deduplication_time_window_secondsDEDUPLICATION_TIME_WINDOW_SECONDS5Duration in seconds for the deduplication time window
default_notifiersDEFAULT_NOTIFIERSn/aList of notifiers which are enabled for all rules
notifiers_xNOTIFIERS_Xn/aList of notifiers with their settings
aws.role_arnAWS_ROLE_ARNn/aAWS Role ARN to use with AWS actions
aws.external_idAWS_ROLE_EXTERNAL_IDn/aAWS External ID used to assume roles with AWS actions. This field is ignored if aws.role_arn is not set.
aws.regionAWS_REGIONn/aAWS Region to use, it should be specified along aws.access_key and aws.secret_key
aws.access_keyAWS_ACCESS_KEYn/aAWS Access Key to use, it should be specified along aws.region and aws.secret_key
aws.secret_keyAWS_SECRET_KEYn/aAWS Access Key to use, it should be specified along aws.region and aws.access_key

Example

listen_address: "0.0.0.0"
listen_port: "2803"
rules_files: "./rules.yaml"
kubeconfig: "./kubeconfig.yaml"

default_notifiers:
  - slack

aws:
 role_arn: arn:aws:iam::<account_number>:role/<role_name>
 external_id: <external_id>
 region: <region> # if not specified, default region from provider credential chain will be used
 access_key: <access_key> # if not specified, default access_key from provider credential chain will be used
 secret_key: <secret_key> # if not specified, default secret_key from provider credential chain will be used

notifiers:
  slack:
    webhook_url: "https://hooks.slack.com/services/XXXX"
    username: "Falco Talon"
    footer: ""

See here for the settings of the notifers.

4 - Installation and Usage

How to install and use Falco Talon

4.1 - Usage

How to use Falco Talon
$ falco-talon --help

Falco Talon is a Response Engine for managing threats in Kubernetes 
It enhances the solutions proposed by Falco community with a dedicated, 
no-code solution. With easy rules, you can perform actions over compromised pods

Usage:
  falco-talon [command]

Available Commands:
  check       Check Falco Talon Rules file
  completion  Generate the autocompletion script for the specified shell
  help        Help about any command
  server      Start Falco Talon
  version     Print version of Falco Talon.

Flags:
  -c, --config string       Falco Talon Config File (default "/etc/falco-talon/config.yaml")
  -h, --help                help for falco-talon
  -r, --rules stringArray   Falco Talon Rules File (default [/etc/falco-talon/rules.yaml])

Use "falco-talon [command] --help" for more information about a command.
$ falco-talon server --help

Start Falco Talon

Usage:
  falco-talon server [flags]

Flags:
  -h, --help   help for server

Global Flags:
  -c, --config string       Falco Talon Config File (default "/etc/falco-talon/config.yaml")
  -r, --rules stringArray   Falco Talon Rules File (default [/etc/falco-talon/rules.yaml])
$ falco-talon check --help

Check Falco Talon Rules file

Usage:
  falco-talon check [flags]

Flags:
  -h, --help   help for check

Global Flags:
  -c, --config string       Falco Talon Config File (default "/etc/falco-talon/config.yaml")
  -r, --rules stringArray   Falco Talon Rules File (default [/etc/falco-talon/rules.yaml])

4.2 - Connect Falcosidekick to Falco Talon

How to receive the Falco Events from Falcosidekick

Once you have installed Falco Talon with Helm in the falco namespace, you have to connect Falcosidekick by adding the flag --set falcosidekick.config.webhook.address=http://falco-talon:2803

helm install falco falcosecurity/falco --namespace falco \
  --create-namespace \
  --set tty=true \
  --set falcosidekick.enabled=true \
  --set falcosidekick.config.webhook.address=http://falco-talon:2803

4.3 - Installation from the sources

How to install Falco Talon locally from the sources

Todo

4.4 - Installation in k8s with Helm

How to install Falco Talon in Kubernetes with Helm

Helm

The helm chart is available in this folder deployment/helm. Two main config files are provided:

  • values.yaml allows you to configure the static settings of Falcon Talon and its deployment
  • rules.yaml contains the rules to set

Clone and install

Git clone is used to target and create a copy of the falco-talon repository:

git clone https://github.com/Falco-Talon/falco-talon.git

Once downloaded, change directory to the Helm folder before running the helm install command:

cd falco-talon/deployment/helm/
helm install falco-talon . -n falco --create-namespace

4.5 - Prometheus metrics

Prometheus metrics

Falco Talon exposes a /metrics endpoint to with some metrics in the Prometheus format.

# HELP action_total number of actions
# TYPE action_total counter
action_total{action="Disable outbound connections",actionner="kubernetes:networkpolicy",event="Test logs",namespace="falco",otel_scope_name="github.com/Falco-Talon/falco-talon",otel_scope_version="devel",pod="falco-5b7kc",rule="Suspicious outbound connection",status="failure"} 6
action_total{action="Terminate Pod",actionner="kubernetes:terminate",event="Test logs",namespace="falco",otel_scope_name="github.com/Falco-Talon/falco-talon",otel_scope_version="devel",pod="falco-5b7kc",rule="Suspicious outbound connection",status="failure"} 6
# HELP event_total number of received events
# TYPE event_total counter
event_total{event="Unexpected outbound connection destination",otel_scope_name="github.com/Falco-Talon/falco-talon",otel_scope_version="devel",priority="Critical",source="syscalls"} 2
# HELP match_total number of matched events
# TYPE match_total counter
match_total{event="Unexpected outbound connection destination",otel_scope_name="github.com/Falco-Talon/falco-talon",otel_scope_version="devel",priority="Critical",rule="Suspicious outbound connection",source="syscalls"} 2

5 - Rules

The rules define the mapping between the Falco events and the actions to run

Syntax

The syntax for the rules files is:

- action: <string,mandatory>
  actionner: <string,mandatory>
  continue: <bool>
  ignore_errors: <bool>
  parameters:
    <string>: <string>
    <string>:
      - <string>
      - <string>
    <string>:
      <string>: <string>
      <string>: <string>

- rule: <string,mandatory>
  match:
    rules:
      - <string>
      - <string>
    priority: <string>
    tags:
      - <string>, <string>, <string>
      - <string>, <string>
    output_fields:
      - <string>=<string>, <string>=<string>
      - <string>!=<string>, <string>=<string>
  continue: <bool>
  dry_run: <bool>
  actions:
    - action: <string,mandatory>
    - action: <string,mandatory>
      actionner: <string,mandatory>
      continue: <bool>
      ignore_errors: <bool>
      parameters:
        <string>: <string>
        <string>:
          - <string>
          - <string>
        <string>:
          <string>: <string>
          <string>: <string>
  notifiers:
    - <string>
    - <string>

The rules files contain 2 types of blocks:

  • action: defines an action that can be reused by different rules
  • rule: defines a rule to match with events and run actions

Action

For the action block, the settings are:

  • action: (mandatory) name of action to trigger
  • actionner: name of the actionner to use
  • continue: if true, no more action are applied after this one (each actionner has its own default value).
  • ignore_errors: if true, ignore the errors and avoid to stop at this action.
  • parameters: key:value map of parameters for the action. value can be a string, an array (slice) or a map.

Rule

For the rule block, the settings are:

  • rule: (mandatory) Name of your rule
  • match: the section to define the criterias to match
    • rules: (list) (OR logic) Falco rules to match. If empty, all rules match.
    • priority: Priority to match. If empty, all priorities match. Syntax is like: >=Critical, <Warning, Debug.
    • tags: (list) (OR logic) Comma separated lists of Tags to match (AND logic). If empty, all tags match.
    • output_fields: (list) (OR logic) Comma separated lists of key:comparison:value for Output fields to match (AND logic). If emtpy, all output fields match.
  • actions: the list of actions to sequentially run, they can refer to an action block or defined locally
    • action: (mandatory) name of action to trigger, can refer to an action block
    • actionner: name of the actionner to use
    • continue: if true, no more action are applied after this one (each actionner has its own default value).
    • ignore_errors: if true, ignore the errors and avoid to stop at this action.
    • parameters: key:value map of parameters for the action. value can be a string, an array (slice) or a map.
  • continue: if true, no more rule are compared after the rule has been triggered (default is true).
  • dry_run: if true: the actions are not ran (default: false).
  • notifiers: list of notifiers to enabled for the action, in addition with the defaults.

Example

In the below YAML manifest, we can see two different Talon actions - Terminate Pod and Disable outbound connections.

  1. The Terminate Pod action has a matching actionner to gracefully terminate a running workload with kubernetes:terminate.
  2. The Disable outbound connections action enforces a Kubernetes NetworkPolicy through kubernetes:networkpolicy.

Finally, the two actions are initiated as instant response actions when the matching Falco rule Unexpected outbound connection destination is triggered.

- action: Terminate Pod
  actionner: kubernetes:terminate
  parameters:
    ignoreDaemonsets: false
    ignoreStatefulsets: true

- action: Disable outbound connections
  actionner: kubernetes:networkpolicy
  parameters:
    allow:
      - "192.168.1.0/24"
      - "172.17.0.0/16"
      - "10.0.0.0/32"

- rule: Suspicious outbound connection
  match:
    rules:
      - Unexpected outbound connection destination
  actions:
    - action: Disable outbound connections
      ignore_errors: true
    - action: Terminate Pod # ref to a re-usable action
      parameters:
        gracePeriods: 2

6 - Actionners

Actionners are the built-it actions to react to the events

The Actionners define the actions to apply when an event matches a rule, they are named with pattern category:action.

The category allows to group actions and avoid multiple initializations (eg, multi Kubernetes API client, multi AWS clients, …).

Each actionner is configured with parameters, a map of values passed to the action. The values can be a string, a list (array) or a map (map[string]string).

Example:

- action: Terminate the pod
  actionner: kubernetes:terminate
  parameters:
    grace_period_seconds: 5
    ignore_daemonsets: true
    ignore_statefulsets: true
    min_healthy_replicas: 33%

- action: Labelize the pod
  actionner: kubernetes:labelize
  parameters:
    labels:
      suspicious: true

6.1 - List of Actionners

Available actionners

The required fields are the field elements that must be present in your Falco events to allow the actionner to do its work.

kubernetes

The category kubernetes can be initialized with a kubeconfig file when Falco Talon runs outside Kubernetes.

kubernetes:terminate

  • Description: Terminate the pod
  • Continue: false
  • Parameters:
    • grace_period_seconds: The duration in seconds before the pod should be deleted. The value zero indicates delete immediately.
    • ignore_daemonsets: If true, the pods which belong to a Daemonset are not terminated.
    • ignore_statefulsets: If true, the pods which belong to a Statefulset are not terminated.
    • min_healthy_replicas: Minimum number of healthy pods to allow the termination, can be an absolute or % value (the value must be a quoted string).
  • Required fields:
    • k8s.pod.name
    • k8s.ns.name
  • Source: syscalls

Example:

- action: Terminate the pod
  actionner: kubernetes:terminate
  parameters:
    grace_period_seconds: 5
    ignore_daemonsets: true
    ignore_statefulsets: true
    min_healthy_replicas: 33%

kubernetes:labelize

  • Description: Add, modify or delete the labels of the pod
  • Continue: true
  • Parameters:
    • labels: key:value map of labels to add/modify/delete (empty value means label deletion)
  • Required fields:
    • k8s.pod.name
    • k8s.ns.name
  • Source: syscalls

Example:

- action: Labelize the pod
  actionner: kubernetes:labelize
  parameters:
    labels:
      suspicious: true

kubernetes:networkpolicy

  • Description: Create, update a network policy to block all egress traffic for pod
  • Continue: true
  • Parameters:
    • allow: list of CIDR to allow anyway (eg: private subnets)
  • Required fields:
    • k8s.pod.name
    • k8s.ns.name
  • Source: syscalls

Example:

- action: Create a network policy
  actionner: kubernetes:networkpolicy
  parameters:
    allow:
      - 192.168.1.0/24
      - 172.17.0.0/16

kubernetes:exec

  • Description: Exec a command in a pod
  • Continue: true
  • Parameters:
    • shell: SHELL used to run the command (default: /bin/sh)
    • command Command to run
  • Required fields:
    • k8s.pod.name
    • k8s.ns.name
  • Source: syscalls

Example:

- action: Exec a command into the pod
  actionner: kubernetes:exec
  parameters:
    shell: /bin/bash
    command: "ps awxuf"

kubernetes:script

  • Description: Run a script in a pod
  • Continue: true
  • Parameters:
    • shell: SHELL used to run the script (default; /bin/sh)
    • script: Script to run (use | to use multilines) (can’t be used at the same time than file)
    • file: Shell script file (can’t be used at the same time than script)
  • Required fields:
    • k8s.pod.name
    • k8s.ns.name
  • Source: syscalls

Example:

- action: Run a script into the pod
  actionner: kubernetes:script
  parameters:
    shell: /bin/bash
    script: |
      ps awxuf
      netstat -lpauten
      top -n 1      

kubernetes:log

  • Description: Get logs from a pod
  • Continue: true
  • Parameters:
    • tail_lines: The number of lines from the end of the logs to show (default: 1000)
  • Required fields:
    • k8s.pod.name
    • k8s.ns.name
  • Source: syscalls

Example:

- action: Get logs of the pod
  actionner: kubernetes:log
  parameters:
    tail_lines: 200

kubernetes:delete

  • Description: Delete the resource
  • Continue: false
  • Parameters: N/A
  • Required fields:
    • ka.target.resource
    • ka.target.name
    • ka.target.namespace
  • Source: k8saudit

Example:

- action: Delete the suspicious resource
  actionner: kubernetes:delete
  parameters:
    tail_lines: 200

calico

The category calico can be initialized with a kubeconfig file when Falco Talon runs outside Kubernetes.

calico:networkpolicy

  • Description: Create a Calico Network Policy to block the egress traffic to a specific IP
  • Continue: true
  • Parameters:
    • allow: list of CIDR to allow anyway (eg: private subnets) (default: 0.0.0.0/0)
    • order: order of the network policy
  • Required fields:
    • fd.sip or fd.rip
  • Source: syscalls

Example:

- action: Create Calico netpol
  actionner: calico:networkpolicy
  parameters:
    order: 20

aws:lambda

  • Description: Invoke an AWS lambda forwarding the Falco event payload
  • Continue: true
  • Parameters:
    • aws_lambda_name: Lambda name to call. Lambda must reside in the same region as your default credential provider or static region provided in configuration.
    • aws_lambda_alias_or_version: Lambda alias or version to call. (default: $LATEST)
    • aws_lambda_invocation_type: Invocation type for Lambda. Accepted values: RequestResponse, Event, DryRun. (default: RequestResponse)
  • Required AWS access:
    • sts:getCallerIdentity
    • lambda:InvokeFunction
    • lambda:GetFunction
  • Source: any

Example:

- action: Invoke Lambda function
  actionner: aws:lambda
  parameters:
    aws_lambda_name: sample-function
    aws_lambda_alias_or_version: $LATEST
    aws_lambda_invocation_type: RequestResponse

7 - Notifiers

Notifiers are the built-it outputs to forward the result of the Falco Talon actions

The Notifiers define which outputs to notify with the result of the actions.

The configuration file contains the list of notifiers to enable by default and the settings for each notifier.

Example:

default_notifiers: # these notifiers will be enabled for all rules
  - k8sevents
  - loki
  - smtp
  - elasticsearch

notifiers:
  loki:
    host_port: https://logs-prod-eu-west-0.grafana.net
    user: 99999
    api_key: xxxxx
  smtp:
    host_port: localhost:1025
    from: falco@falcosecurity.org
    to: user@test.com, other@test.com
    # user: test
    # password: test
    format: html
    tls: false
  elasticsearch:
    url: http://localhost:9200
    create_index_template: true
    number_of_shards: 1
    number_of_replicas: 1

7.1 - List of Notifiers

Available notifiers

K8s Events

This notifiers creates a k8s event in the target resource namespace.

Settings

No configuration is requested.

Result

LAST SEEN   TYPE     REASON                                    OBJECT                      MESSAGE
18s         Normal   falco-talon:kubernetes:labelize:success   pod/cncf-55696bc998-ql5qd   Status: success...
18s         Normal   falco-talon:kubernetes:labelize:success   pod/cncf-55696bc998-ql5qd   Status: success...
action: kubernetes:labelize
apiVersion: v1
eventTime: "2024-02-27T13:54:30.008721Z"
firstTimestamp: null
involvedObject:
  kind: Pod
  name: cncf-55696bc998-ql5qd
  namespace: default
kind: Event
lastTimestamp: null
message: "Status: success\nMessage: action\nRule: Terminal shell in container\nAction:
  Labelize Pod as Suspicious\nActionner: kubernetes:labelize\nEvent: A shell was spawned
  in a container with an attached terminal (evt_type=execve user=root user_uid=0 user_loginuid=-1
  process=sh proc_exepath=/usr/bin/dash parent=runc command=sh -c command -v bash
  >/dev/null && exec bash || exec sh terminal=34817 exe_flags=EXE_WRITABLE container_id=f13c72275fd4
  container_image=docker.io/library/debian container_image_tag=latest container_name=cncf
  k8s_ns=default k8s_pod_name=cncf-55696bc998-ql5qd)\nnamespace: default\npod: cncf-55696bc998-ql5qd\nOutput:
  \nthe pod \"cncf-55696bc998-ql5qd\" in the namespace \"default\" has been labelized\nTraceID:
  cc84de57-7617-4359-ad40-1a7a8d854743\n"
metadata:
  creationTimestamp: "2024-02-27T13:54:30Z"
  generateName: falco-talon-
  name: falco-talon-rf2dz
  namespace: default
  resourceVersion: "32141229"
  uid: a407b246-f2b5-46ba-8146-ebe474302604
reason: falco-talon:kubernetes:labelize:success
reportingComponent: falcosecurity.org/falco-talon
reportingInstance: falco-talon
source:
  component: falco-talon
type: Normal

Slack

Settings

SettingDefaultDescription
webhook_urln/aWebhook URL
iconhttps://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpgAvatar for messages
usernameFalco TalonUsername for messages
footerhttps://github.com/Issif/falco-talonFooter for messages
formatlongFormat for messages (`longshort`)

Example

notifiers:
  slack:
    webhook_url: "https://hooks.slack.com/services/XXXX"
    icon: "https://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpg"
    username: "Falco Talon"
    footer: "https://github.com/Falco-Talon/falco-talon"
    format: long

Results

with format: short:

images/slack_short.png

with format: long:

images/slack_long.png

Loki

Settings

SettingDefaultDescription
urln/ahttp://{domain or ip}:{port}
usern/aUser for Grafana Logs
api_keyn/aAPI Key for Grafana Logs
tenantn/aAdd the Tenant header
custom_headersn/aCustom HTTP Headers

Result

images/loki_grafana.png

Example

notifiers:
  loki:
    host_port: "https://xxxxx"
    user: "xxxx"
    api_key: "xxxxx"

Elasticsearch

Settings

SettingDefaultDescription
host_portn/ahttp://{domain or ip}:{port}
usern/aUser for Grafana Logs
passwordn/aPassword for Grafana Logs
indexfalco-talonElasticsearch index
suffixdailyDate suffix for index rotation : daily (default), monthly, annually, none
create_index_templatetrueCreate the index template at the init if it doesn’t exist
number_of_shards3Number of shards for the index (if create_index_template is true)
number_of_replicas3Number of replicas for the index (if create_index_template is true)
custom_headersn/aCustom HTTP Headers

Example

notifiers:
  elasticsearch:
    url: "http://localhost:9200"
    create_index_template: true
    number_of_shards: 1
    number_of_replicas: 1

SMTP

Settings

SettingDefaultDescription
host_portn/aHost:Port of SMTP server
usern/aUser for SMTP
passwordn/aPassword for SMTP
fromn/aFrom
ton/aTo (comma separated list of adresses)
formathtmlFormat of the email (text, html)
tlsfalseUse TLS connection

Example

notifiers:
  smtp:
    host_port: "localhost:1025"
    from: "falco@falcosecurity.org"
    to: "user@test.com, other@test.com"
    user: "xxxx"
    password: "xxxxx"
    format: "html"
    tls: false

Results

with format: html:

./images/smtp_html.png

with format: text:

images/smtp_text.png

Webhook

Settings

SettingDefaultDescription
urln/aURL
http_methodPOSTHTTP Method
user_agentFalco-TalonUser Agent
content_typeapplication/json; charset=utf-8Content Type
custom_headersn/aCustom HTTP Headers

Example

notifiers:
  webhook:
    url: "http://xxxx"
    http_method: "POST"
    user_agent: "Falco-Talon"
    content_type: "application/json; charset=utf-8"
    custom_headers:
      Authorization: "Bearer xxxxx"

8 - Reference

Low level reference docs for your project.

Todo

9 - Contribution Guidelines

How to contribute to the docs

These basic sample guidelines assume that your Docsy site is deployed using Netlify and your files are stored in GitHub. You can use the guidelines “as is” or adapt them with your own instructions: for example, other deployment options, information about your doc project’s file structure, project-specific review guidelines, versioning guidelines, or any other information your users might find useful when updating your site. Kubeflow has a great example.

Don’t forget to link to your own doc repo rather than our example site! Also make sure users can find these guidelines from your doc repo README: either add them there and link to them from this page, add them here and link to them from the README, or include them in both locations.

We use Hugo to format and generate our website, the Docsy theme for styling and site structure, and Netlify to manage the deployment of the site. Hugo is an open-source static site generator that provides us with templates, content organisation in a standard directory structure, and a website generation engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.

All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.

Quick start with Netlify

Here’s a quick guide to updating the docs. It assumes you’re familiar with the GitHub workflow and you’re happy to use the automated preview of your doc updates:

  1. Fork the Goldydocs repo on GitHub.
  2. Make your changes and send a pull request (PR).
  3. If you’re not yet ready for a review, add “WIP” to the PR name to indicate it’s a work in progress. (Don’t add the Hugo property “draft = true” to the page front matter, because that prevents the auto-deployment of the content preview described in the next point.)
  4. Wait for the automated PR workflow to do some checks. When it’s ready, you should see a comment like this: deploy/netlify — Deploy preview ready!
  5. Click Details to the right of “Deploy preview ready” to see a preview of your updates.
  6. Continue updating your doc and pushing your changes until you’re happy with the content.
  7. When you’re ready for a review, add a comment to the PR, and remove any “WIP” markers.

Updating a single page

If you’ve just spotted something you’d like to change while using the docs, Docsy has a shortcut for you:

  1. Click Edit this page in the top right hand corner of the page.
  2. If you don’t already have an up to date fork of the project repo, you are prompted to get one - click Fork this repository and propose changes or Update your Fork to get an up to date version of the project to edit. The appropriate page in your fork is displayed in edit mode.
  3. Follow the rest of the Quick start with Netlify process above to make, preview, and propose your changes.

Previewing your changes locally

If you want to run your own local Hugo server to preview your changes as you work:

  1. Follow the instructions in Getting started to install Hugo and any other tools you need. You’ll need at least Hugo version 0.45 (we recommend using the most recent available version), and it must be the extended version, which supports SCSS.

  2. Fork the Goldydocs repo repo into your own project, then create a local copy using git clone. Don’t forget to use --recurse-submodules or you won’t pull down some of the code you need to generate a working site.

    git clone --recurse-submodules --depth 1 https://github.com/google/docsy-example.git
    
  3. Run hugo server in the site root directory. By default your site will be available at http://localhost:1313/. Now that you’re serving your site locally, Hugo will watch for changes to the content and automatically refresh your site.

  4. Continue with the usual GitHub workflow to edit files, commit them, push the changes up to your fork, and create a pull request.

Creating an issue

If you’ve found a problem in the docs, but you’re not sure how to fix it yourself, please create an issue in the Goldydocs repo. You can also create an issue about a specific page by clicking the Create Issue button in the top right hand corner of the page.

Useful resources