diff --git a/ci/vale/dictionary.txt b/ci/vale/dictionary.txt
index f080db5adca..884e2ec62f2 100644
--- a/ci/vale/dictionary.txt
+++ b/ci/vale/dictionary.txt
@@ -631,6 +631,7 @@ javac
javascript
jdbc
jdk
+Jellyfin
jenkinsfile
jetpack
jez
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/DLNAremoval.png b/docs/applications/media-servers/how-to-install-jellyfin/DLNAremoval.png
new file mode 100644
index 00000000000..9e70a33c8b8
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/DLNAremoval.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/homemenu.png b/docs/applications/media-servers/how-to-install-jellyfin/homemenu.png
new file mode 100644
index 00000000000..b7cdabed730
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/homemenu.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/index.md b/docs/applications/media-servers/how-to-install-jellyfin/index.md
new file mode 100644
index 00000000000..e2862152ef3
--- /dev/null
+++ b/docs/applications/media-servers/how-to-install-jellyfin/index.md
@@ -0,0 +1,191 @@
+
+---
+author:
+ name: The Linux Gamer
+description: 'Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media, this guide walks you through installing it on a Linode'
+keywords: ["Jellyfin", "Media Server", "PLEX"]
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+modified: 2019-08-07
+modified_by:
+ name: Linode
+published: 2019-08-07
+title: How to Install Jellyfin on Linux
+---
+Jellyfin is an open source media library management and streaming platform, similar to [Plex](https://www.plex.tv/). This document will guide you through the process of installing and configuring **Jellyfin** on your Linode running Ubuntu 18.04.
+
+In this guide you will complete the following:
+
+- [Install and configure Jellyfin on a Linode](/docs/applications/media-servers/how-to-install-jellyfin/#install-jellyfin)
+- [Create a Reverse Proxy for Jellyfin](/docs/applications/media-servers/how-to-install-jellyfin/#create-a-reverse-proxy-for-jellyfin)
+
+## Before you Begin
+
+1. If you have not set up your Linode yet, check out our [Getting Started](https://www.linode.com/docs/getting-started/) guide and complete the steps for setting your Linode’s hostname and timezone.
+
+2. Follow up with our [Securing Your Server](https://www.linode.com/docs/security/securing-your-server/) guide to create a standard user account with `sudo` privileges.
+
+3. Run the following command to upgrade your packages:
+
+ sudo apt-get update && sudo apt-get upgrade
+
+ {{< note >}}
+This guide is written for a non-root user. Commands that require elevated privileges are prefixed with `sudo`. If you’re not familiar with the `sudo` command, see the [Users and Groups](https://www.linode.com/docs/tools-reference/linux-users-and-groups/) guide.
+ {{< /note >}}
+
+## Install Jellyfin
+
+1. Install and enable HTTPS transport for APT:
+
+ sudo apt install apt-transport-https
+
+2. Enable the Universe repository for all of the `ffmpeg` dependencies:
+
+ sudo add-apt-repository universe
+
+3. Import the GPG signing keys from the Jellyfin team:
+
+ wget -O - https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key | sudo apt-key add -
+
+4. Create a new file located at `/etc/apt/sources.list.d/jellyfin.list`
+
+ sudo touch /etc/apt/sources.list.d/jellyfin.list
+
+5. Add the Jellyfin `apt` repo to your Linode.
+
+ echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/ubuntu $( lsb_release -c -s ) main" | sudo tee /etc/apt/sources.list.d/jellyfin.list
+
+ {{< note >}}
+Current supported releases are `Cxenial`, `bionic`, `cosmic`, and `disco`. Since we're using Ubuntu 18.04, `lsb_release` will become `bionic`.
+{{< /note >}}
+
+ The output, and the content of the `/etc/apt/sources.list.d/jellyfin.list`, should look something like this:
+
+ {{< output >}}
+deb [arch=amd64] https://repo.jellyfin.org/ubuntu bionic main
+{{< /output >}}
+
+6. Finally, update your packages and install Jellyfin
+
+ sudo apt update && sudo apt install jellyfin
+
+## Configure Jellyfin
+
+Now that Jellyfin is successfully installed, it needs to be configured and pointed to our media.
+
+### Initial Setup
+
+1. Setting up Jellyfin is done through the web interface. Before you can access the web interface, disconnect from SSH and create a secure tunnel via SSH from your local host to your Linode.
+
+ ssh user@192.0.2.1 -L 8888:localhost:8096
+
+ {{< note >}}
+Substitute `user` with the `sudo user` on your Linode, and `192.0.2.1` with your Linode's IP address.
+{{< /note >}}
+
+1. Open your browser and navigate to `http://localhost:8888/`. You should now see the Jellyfin first-time configuration screen. Start by selecting your preferred language from the drop down menu. Then click the **Next** button to continue.
+
+ 
+
+1. Create your user account and password. Then click the **Next** button to continue.
+
+ 
+
+1. Now you'll create the directories to store your media on your Linode. For example, if you want to have music and movies on your server, you would create a directory to store them by using the following command in your terminal:
+
+ cd ~/
+ sudo mkdir -p jellyfin-media/music && sudo mkdir jellyfin-media/movies
+
+1. Back in your browser, now that your account is created, we can add your media. Click on the **Add Media Library** button to begin this process.
+
+ 
+
+ {{< note >}}
+Each kind of content type provides a different set of options for you to configure, such as where you would like your metadata retrieved from, etc.
+{{< /note >}}
+
+1. Content in Jellyfin is organized into Libraries. Libraries can have multiple directories from which they aggregate their media. You can specify directories using the Folders plus **(+)** button. Click the **(+)** button to add the folder you created earlier.
+
+ 
+
+1. In the **Folders** field, enter the full path to your folder (`/home/username/jellyfin-media/movies`) then click the **Ok** button.
+
+ 
+
+1. You can add as many libraries as you'd like both now and [later through your dashboard](#add-and-organize-media)
+ Click the blue **Next** button to proceed to the next sections.
+
+1. Select your preferred metadata Language, then click on the **Next** button.
+
+1. Disable port mapping by unchecking the *Enable automatic port mapping* option as this feature can pose a security risk in a cloud environment. Port Mapping is generally enabled in a local environment behind a home router, where you may want your Jellyfin server to be able to seamlessly connect to other devices.
+
+ 
+
+1. Click the **Next** button. Your setup is now complete and you'll be required to sign in as the user with the password you setup earlier.
+
+### Disable Unneeded Features (Recommended)
+
+[DLNA](https://en.wikipedia.org/wiki/Digital_Living_Network_Alliance) is a protocol that incorporates [Universal Plug and Play](https://en.wikipedia.org/wiki/Universal_Plug_and_Play) (or UPnP) standards for digital media sharing across devices. As port `1900` will be openly available and any DLNA device or application can have full unrestricted access to your content, we recommend disabling DLNA if you won’t be using it.
+
+ Click the "hamburger" menu in the top left corner of Jellyfin, choose *Dashboard*, and on the left side of the screen choose *DLNA*, then disable and save your DLNA settings.
+
+
+
+### Add and Organize Media
+
+- You can add as many libraries as you'd like through the *Dashboard* under *Libraries* at any time.
+
+ 
+
+- Media can be added to individual folders from inside your Linode using various [file transfer tools](https://www.linode.com/docs/tools-reference/file-transfer/) and [download methods](https://www.linode.com/docs/tools-reference/tools/download-resources-from-the-command-line-with-wget/).
+- Once files in a folder are added to your Jellyfin server, they can be accessed from your *Home Menu* by clicking on the Home icon at top left of the page after selecting the hamburger menu.
+
+ 
+
+## Create a Reverse Proxy for Jellyfin
+
+Jellyfin primarily works as a web frontend for your media. That means you'll generally want to proxy the default Jellyfin websocket to requests. Jellyfin supports a [large number of server software solutions](https://jellyfin.org/docs/general/administration/reverse-proxy.html#apache) for this purpose, though in this guide, the example will be [Apache](http://httpd.apache.org/).
+
+1. Install Apache with the following command:
+
+ sudo apt install apache2
+
+1. Enable proxy settings for Apache with the following commands:
+
+ sudo a2enmod proxy
+ sudo a2enmod proxy_http
+
+1. Open a new virtual host file for your configuration. Replace "example.com" in this example with the domain name you'll be using:
+
+ sudo nano /etc/apache2/sites-available/jellyfin.example.com.conf
+
+ {{< note >}}
+Although nano is used in this example, feel free to use the text editor of your choice.
+{{< /note >}}
+
+1. Use the following Apache virtual host configuration to create your reverse proxy. Replace `jellyfin.example.com` with your domain/subdomain.
+
+ {{< file "/etc/apache2/sites-available/jellyfin.example.com.conf" >}}
+
+ ServerName jellyfin.example.com
+ ErrorLog /var/log/apache2/jellyfin-error.log
+ CustomLog /var/log/apache2/jellyfin-access.log combined
+
+ ProxyPreserveHost On
+
+ ProxyPass "/embywebsocket" "ws://127.0.0.1:8096/embywebsocket"
+ ProxyPassReverse "/embywebsocket" "ws://127.0.0.1:8096/embywebsocket"
+
+ ProxyPass "/" "http://127.0.0.1:8096/"
+ ProxyPassReverse "/" "http://127.0.0.1:8096/"
+
+{{< /file >}}
+
+1. Enable your new website:
+
+ sudo a2ensite jellyfin.example.com.conf
+
+1. Restart Apache to fully enable your settings:
+
+ sudo systemctl restart apache2
+
+You may also want to [set up SSL encryption for this virtual host](https://www.linode.com/docs/quick-answers/websites/secure-http-traffic-certbot/). For more information regarding this configuration, see Jellyfin's [reverse proxy documentation](https://jellyfin.readthedocs.io/en/latest/administrator-docs/reverse-proxy/#apache)
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-account-creation.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-account-creation.png
new file mode 100644
index 00000000000..8d335a6d772
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-account-creation.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-disable-port-mapping.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-disable-port-mapping.png
new file mode 100644
index 00000000000..d2956bc50c2
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-disable-port-mapping.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-folder-library.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-folder-library.png
new file mode 100644
index 00000000000..9fd766fbd10
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-folder-library.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-language-set-up.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-language-set-up.png
new file mode 100644
index 00000000000..c59bf1240b1
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-language-set-up.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-dashboard.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-dashboard.png
new file mode 100644
index 00000000000..b418663ff25
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-dashboard.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-folders.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-folders.png
new file mode 100644
index 00000000000..83e45e06d22
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-folders.png differ
diff --git a/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-setup.png b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-setup.png
new file mode 100644
index 00000000000..0734b9da08b
Binary files /dev/null and b/docs/applications/media-servers/how-to-install-jellyfin/jellyfin-library-setup.png differ
diff --git a/docs/development/bash/_index.md b/docs/development/bash/_index.md
new file mode 100644
index 00000000000..31920c310a4
--- /dev/null
+++ b/docs/development/bash/_index.md
@@ -0,0 +1,11 @@
+---
+author:
+ name: Linode
+ email: docs@linode.com
+description: 'Bash is a programming language and a shell for UNIX systems. It provides a number of commonly used programming functions and operators, as well as some file specific operators.'
+keywords: ["bash","shell","programming","language"]
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+title: Bash
+published: 2019-10-09
+show_in_lists: true
+---
\ No newline at end of file
diff --git a/docs/development/bash/bash1/index.md b/docs/development/bash/bash1/index.md
new file mode 100644
index 00000000000..363af0ca2ab
--- /dev/null
+++ b/docs/development/bash/bash1/index.md
@@ -0,0 +1,699 @@
+---
+author:
+ name: Mihalis Tsoukalos
+ email: mihalistsoukalos@gmail.com
+description: 'An introduction to bash shell scripting, including variables, if statements, loops, how to get user input, and working with files and directories.'
+keywords: ["UNIX", "shell", "bash", "programming", "script"]
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+published: 2019-09-27
+modified_by:
+ name: Linode
+title: 'Introduction to Bash Shell Scripting'
+contributor:
+ name: Mihalis Tsoukalos
+ link: https://www.mtsoukalos.eu/
+external_resources:
+ - '[GNU Bash](https://www.gnu.org/software/bash/)'
+---
+
+## Introduction
+
+This guide is an introduction to bash shell programming. Bash shell programming empowers Linux users to take programmatic control over the Linux operating system. The bash shell provides a number of concepts common to many other programming languages, so if you know another language then you should be able to pick up bash with relative ease.
+
+## In This Guide
+
+Among other things, you will learn about:
+
+- [Bash Scripts](#bash-scripts)
+- [Variables](#defining-and-using-variables)
+- [How to get user input](#getting-user-input)
+- [`if` statements](#the-if-statement)
+- [How to use environment variables](#using-unix-environment-variables)
+- [Loops](#loops)
+- [How to use command line arguments](#command-line-arguments)
+- [`case` statements](#the-case-statement)
+- [How to combine commands](#combining-commands-in-bash-scripts)
+- [How to work with files and directories](#working-with-files-and-directories)
+
+{{< note >}}
+This guide is written for a non-root user. Depending on your configuration, some commands might require the help of `sudo` in order to properly execute. If you are not familiar with the `sudo` command, see the [Users and Groups](/docs/tools-reference/linux-users-and-groups/) guide.
+{{< /note >}}
+
+## Bash Basics
+
+### The bash Executable
+
+The bash shell is an executable file. The executable file for the bash shell can be usually found inside `/bin` – its full
+path being `/bin/bash`. Please keep this file path in mind as it will be used in all
+bash scripts.
+
+### Bash Scripts
+
+The following code is the "Hello World" program written in `bash(1)`:
+
+{{< file "hello_world.sh" bash >}}
+#!/bin/bash
+
+echo "Hello World!"
+{{< /file >}}
+
+The first line is required for the bash script to become autonomous and executable
+as a command. The `#!` characters are called a *shebang*, and instruct Linux to use following path as the file interpreter. The `.sh` file extension is not required but it is good to have it in
+order to inform people that this is a shell script and not a binary file.
+
+Notice that `echo` is a bash shell built-in command that outputs text. All shells have their own built-in
+commands.
+
+In order for a bash script to be executable, it needs to have the appropriate
+file permissions. To give a file permissions that allow it to be executable, use
+the `chmod +x file.sh` command, substituting `file.sh` for the name of the file. After that you can execute it as `./file.sh`.
+Alternatively you can use `chmod 755 file.sh`.
+
+For the `hello_world.sh` script to become executable, you will need to run one
+of the following two commands:
+
+ chmod +x hello_world.sh
+ chmod 755 hello_world.sh
+
+After that the file permissions of `hello_world.sh` will be similar to the following:
+
+ ls -l hello_world.sh
+
+{{< output >}}
+-rwxr-xr-x 1 mtsouk staff 32 Aug 1 20:09 hello_world.sh
+{{< /output >}}
+
+{{< note >}}
+You will need to give all bash scripts of this guide the execute file permission
+in order to be able to execute them as regular UNIX commands. For more information on file permissions, see our [Linux Users and Groups Guide](/docs/tools-reference/linux-users-and-groups/).
+{{< /note >}}
+
+Executing `hello_world.sh` will generate the following output:
+
+ ./hello_world.sh
+
+{{< output >}}
+Hello World!
+{{< /output >}}
+
+The `./` in front of the script name tells bash that the file you want to execute is
+in the current directory. This is necessary for executing any file that is not located
+in the `PATH`. The `PATH` *environment variable* contains a list of directories that
+bash will search through for executable commands. You can execute `echo $PATH` to find
+its current value.
+
+{{< note >}}
+The `#` character is used for adding single line comments in bash scripts. The bash shell
+also supports multi line comments, but they are not used as often, so it would be
+better to use multiple single line comments when you want to write bigger comment blocks.
+{{< /note >}}
+
+### Defining and Using Variables
+
+The programming language of the bash shell has support for variables. Variables, like in math, have values that can be declared in a program and later changed or passed around to different functions. Variables
+are illustrated in `vars.sh`, which is as follows:
+
+{{< file "vars.sh" bash >}}
+#!/bin/bash
+
+VAR1="Mihalis"
+myVar="$(pwd)"
+
+echo "My name is ${VAR1}"
+echo -n "and I work from "
+echo $myVar
+
+myVar=`pwd`
+echo $myVar
+{{< /file >}}
+
+There are two variables defined in this example: the first one is called `VAR1` and the second one
+is called `myVar`. Although both variables are defined inside the program, the first
+variable is defined with a direct assignment whereas the second variable is defined
+as the output of an external program, the `pwd(1)` command, which outputs the current working directory. The value of `myVar` depends
+on your place in the filesystem.
+
+The two variables are read as `${VAR1}` and `$myVar`, respectively – both notations work.
+Notice that in order to prevent `echo` from printing a newline character, you will have to
+call it as `echo -n`. Lastly, notice that `"$(pwd)"` and `` `pwd` `` (note the use of backticks instead of quotation marks) are equivalent.
+
+Executing `vars.sh` will generate the following kind of output:
+
+ ./vars.sh
+
+{{< output >}}
+My name is Mihalis
+and I work from /home/mtsouk/
+/home/mtsouk/
+{{< /output >}}
+
+### Getting User Input
+
+The bash shell offers the `read` command for getting user input. However, this is
+rarely used because it makes bash shell scripts less autonomous as it depends on user interaction. Nevertheless, the
+`read.sh` script illustrates the use of `read`:
+
+{{< file "read.sh" bash >}}
+#!/bin/bash
+
+echo -n "What is your name? "
+read name
+
+echo "Hello" "$name!"
+
+echo -n "Please state your name and your surname: "
+read name surname
+echo "Hello" "$name $surname!"
+{{< /file >}}
+
+Executing `read.sh` will generate the following kind of output:
+
+ ./read.sh
+{{< output >}}
+What is your name? Mihalis
+Hello Mihalis!
+Please state your name and your surname: Mihalis Tsoukalos
+Hello Mihalis Tsoukalos!
+{{< /output >}}
+
+The second `read` is different than the first, because it accepts two variable values. The `read` command looks for a space or tab separator in the input text in order to split the text into multiple values. If more than one space is provided, then all remaining values are combined. This means that if the user's surname is a compound of two or more additional words they will all become the value of `$surname`.
+
+The sections on [Environment Variables](#using-unix-environment-variables) and [Command Line Arguments](#command-line-arguments) show alternative ways of retrieving user input that
+is more common in the UNIX world than the `read` command.
+
+### The if statement
+
+The bash shell supports `if` statements using a unique syntax, which
+is illustrated in `whatIf.sh`:
+
+{{< file "whatIf.sh" bash >}}
+#!/bin/bash
+
+VAR1="4"
+VAR2="4"
+
+if [ $VAR1 == 4 ]
+then
+ echo Equal!
+fi
+
+if [ "$VAR1" == 4 ]
+then
+ echo Equal!
+else
+ echo Not equal!
+fi
+
+if [ "$VAR1" == $VAR2 ]
+then
+ echo Equal!
+elif [ "$VAR1" == $VAR1 ]
+then
+ echo Tricky Equal!
+else
+ echo Not equal!
+fi
+{{< /file >}}
+
+`if` statements allow for logic to be applied to a block of code. If the statement is true, the code is executed. `if` statements in bash script use square brackets for the logical condition and also
+have support for `else` and `elif` (else if) branches. Bash supports standard programming language conditional operators such as equals (`==`), not equals (`!=`), less than and greater than (`<`, `>`), and a number of other file specific operators.
+
+All `if` statements contain a conditional express, and a `then` statement, and all statements are ended with `fi`.
+
+As filenames and paths may contain space characters, it is good to embed them in double
+quotes – this has nothing to do with the `if` statement per se. Notice that this unofficial
+rule applies to other variables that might contain space characters in them. This is
+illustrated with the use of the `VAR1` variable. Lastly, the `==` operator is for checking
+string values for equality.
+
+ ./whatIf.sh
+
+{{< output >}}
+Equal!
+Not equal!
+Not equal!
+{{< /output >}}
+
+The `if` statement is used extensively in bash scripts, which means that you are going to
+see it many times in this guide.
+
+### Loops
+
+The bash shell has support for loops, which are illustrated in this section
+of the guide using the code of `loops.sh`:
+
+{{< file "loops.sh" bash >}}
+#!/bin/bash
+
+# For loop
+numbers="One Two Three List"
+for n in $numbers
+do
+ echo $n
+done
+
+for x in {1..4}
+do
+ echo -n "$x "
+done
+echo
+
+for x in ./c*.sh
+do
+ echo -n "$x "
+done
+echo
+
+# While loop
+c=0
+while [ $c -le 5 ]
+do
+ echo -n "$c "
+ ((c++))
+done
+echo
+
+# Until loop
+c=0
+until [ $c -gt 5 ]
+do
+ echo -n "$c "
+ ((c++))
+done
+echo
+{{< /file >}}
+
+{{< note >}}
+
+The bash scripting language offers support for the `break` statement for exiting a loop, and the `continue` statement
+for skipping the current iteration.
+
+{{< /note >}}
+
+The `loops.sh` example begins with three `for` loops. These loops will iterate over values in a series, here represented by the `numbers` list variable or a range like `{1..4}`, and complete the block of code after the `do` command for each value. In a set of four values a loop will iterate four times. Notice that the third `for` loop processes the output of `./c*.sh`, which is equivalent to the output of the `ls ./c*.sh` command – this is a pretty handy way of selecting and processing files from the Linux filesystem.
+
+Similarly, the `while` statement and the `until` statement will continually loop so long as the conditional statement is true (while), or until the statement becomes true (until). The `-le` and `-gt` operators used in the `while` and `until` loops are used strictly to compare numbers, and mean "less than or equal to" and "greater than," respectively.
+
+Executing `loops.sh` will create the following output:
+
+ ./loops.sh
+{{< output >}}
+One
+Two
+Three
+List
+1 2 3 4
+./case.sh ./cla.sh
+0 1 2 3 4 5
+0 1 2 3 4 5
+{{< /output >}}
+
+{{< note >}}
+The `./case.sh` and `./cla.sh` scripts will be created in later sections of this guide.
+{{< /note >}}
+
+## Using UNIX Environment Variables
+
+In this section of the guide you will learn how to read a UNIX environment variable,
+change its value, delete it, and create a new one. This is a very popular way of
+getting user input or reading the setup of the current user.
+
+The related bash shell script is called `env.sh` and is as follows:
+
+{{< file "env.sh" bash >}}
+#!/bin/bash
+
+# Read
+if [[ -z "${PATH}" ]]; then
+ echo "PATH is empty!"
+else
+ echo "PATH: $PATH"
+fi
+
+# Change
+PATH=${PATH}:/tmp
+echo "PATH: $PATH"
+
+# Delete
+export PATH=""
+if [[ -z "${PATH}" ]]; then
+ echo "PATH is empty!"
+else
+ echo "PATH: $PATH"
+fi
+
+# Create
+MYPATH="/bin:/sbin:/usr/bin"
+echo "MYPATH: ${MYPATH}"
+{{< /file >}}
+
+Notice that the `PATH` environment variable is automatically available to the bash script. You can view it's current value in the output of the first `if` statement. The `-z` operator
+tests whether a variable has a length of zero or not and can be pretty handy when
+checking if an environment variable is set or not.
+
+Executing `env.sh` will create the following output:
+
+ ./env.sh
+
+{{< output >}}
+PATH: /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/texbin:/opt/X11/bin
+PATH: /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/texbin:/opt/X11/bin:/tmp
+PATH is empty!
+MYPATH: /bin:/sbin:/usr/bin
+{{< /output >}}
+
+{{< note >}}
+Notice that all changes to environment variables that take place inside a bash
+script will be lost when that bash script ends because they have a local scope.
+{{< /note >}}
+
+## Bash and Command Line Arguments
+
+### Command Line Arguments
+
+The easiest and most common way to pass your own data to scripts is the use of command
+line arguments. For instance, review the following command:
+
+ ./cla.sh 1 2 3
+
+This example command is executing the `cla.sh` command, and supplying a number of arguments, in this case the numbers 1, 2, and 3. Those numbers could be any type of information the bash script needs to execute.
+
+The `cla.sh` bash script demonstrates how to work with command line
+arguments:
+
+{{< file "cla.sh" bash >}}
+#!/bin/bash
+
+echo "Arguments: $@"
+echo "Number of arguments: $#"
+
+for arg in "$@"
+do
+ echo "$arg"
+done
+
+echo "The name of the script is: $0"
+echo "The first argument is: $1"
+
+if [ -x $0 ]
+then
+ echo "$0" file exists!
+fi
+{{< /file >}}
+
+The full list of arguments is stored as `$@` and the number of arguments is stored as `$#`. A `for` loop can be used for iterating over the list of command line arguments. Lastly, the name of the program is always `$0` and the first command line argument, if it exists, is always `$1`.
+
+Executing `cla.sh` will generate the following output:
+
+ ./cla.sh 1 2 3
+
+{{< output >}}
+Arguments: 1 2 3
+Number of arguments: 3
+1
+2
+3
+The name of the script is: ./cla.sh
+The first argument is: 1
+./cla.sh file exists!
+{{< /output >}}
+
+### Checking the Number of Command Line Arguments
+
+In the previous section you learned how to pass command line arguments to a bash script. The following bash script, which is named `nCla.sh`, requires that you pass at least two command line arguments to it:
+
+{{< file "nCla.sh" bash >}}
+#!/bin/bash
+
+if [ "$#" -lt 2 ]
+then
+ echo Need more arguments than $#!
+else
+ echo "Thanks for the $# arguments!"
+fi
+{{< /file >}}
+
+Notice that numeric comparisons require the use of `-lt` in an `if` statement, which
+is an alias for `less than`.
+
+Executing `nCla.sh` with the right number of arguments will generate the following
+output:
+
+ ./nCla.sh 1 2
+
+{{< output >}}
+Thanks for the 2 arguments!
+{{< /output >}}
+
+Executing `nCla.sh` with an insufficient number of arguments will generate the following
+output:
+
+ ./nCla.sh
+
+{{< output >}}
+Need more arguments than 0!
+{{< /output >}}
+
+### Combining Commands in bash Scripts
+
+Bash has the additional capability of executing a combination of commands. This capability is illustrated in
+`combine.sh`:
+
+{{< file "combine.sh" bash >}}
+#!/bin/bash
+
+total=0
+for n in ./*.sh
+do
+ ti=`grep while ${n} | wc -l`
+ ti=$(($ti + 0))
+ if [[ $ti -gt 0 ]]
+ then
+ total=$(($total+$ti))
+ fi
+done
+
+echo "Total:" $total
+{{< /file >}}
+
+The `for` loop in this example iterates over every bash script file in the current working directory.
+The initial value of `ti` is taken from the output of a command with two parts. The first part uses
+`grep` to look for the `while` word in the file that is being processed and the
+second part counts the number of times that the `while` word was found in the
+current file. The `total=$(($total+$ti))` statement is needed for adding the value of `ti` to
+the value of `total`. Additionally, the `ti=$(($ti + 0))` statement is used for
+converting the value of `ti` from string to integer. Last, before exiting, `combine.sh` prints the total number of times the
+`while` word was found in all processed files.
+
+ ./combine.sh
+
+{{< output >}}
+Total: 2
+{{< /output >}}
+
+## The Case Statement
+
+The bash scripting language supports the `case` statement. A case statement provides a number of possible values for a variable and maps code blocks to those values. For example, the case statement included in `case.sh` script below defines a number of possible outputs depending on the number provided as a command line argument:
+
+{{< file "case.sh" bash >}}
+#!/bin/bash
+
+if [ $# -lt 1 ]
+then
+ echo "Usage : $0 integer"
+ exit
+fi
+
+NUM=$1
+echo "Testing ${NUM}"
+
+if [[ ! $NUM =~ ^[0-9]+$ ]] ; then
+ echo "Not an integer"
+ exit
+fi
+
+case $NUM in
+ 0)
+ echo "Zero!"
+ ;;
+ 1)
+ echo "One!"
+ ;;
+ ([2-9]|[1-7][0-9]|80) echo "From 2 to 80"
+ ;;
+ (8[1-9]|9[0-9]|100) echo "From 81 to 100"
+ ;;
+ *)
+ echo "Too big!"
+ ;;
+esac
+
+case 1:${NUM:--} in
+(1:*[!0-9]*|1:0*[89]*)
+ ! echo NAN
+;;
+($((NUM<81))*)
+ echo "$NUM smaller than 80"
+;;
+($((NUM<101))*)
+ echo "$NUM between 81 and 100"
+;;
+($((NUM<121))*)
+ echo "$NUM between 101 and 120"
+;;
+($((NUM<301))*)
+ echo "$NUM between 121 and 300"
+;;
+($((NUM>301))*)
+ echo "$NUM greater than 301"
+;;
+esac
+{{< /file >}}
+
+The script requires a command line argument, which is an integer value. A regular
+expression verifies that the input is a valid positive integer number with the
+help of an `if` statement.
+
+From the presented code you can understand that branches in `case` statements do
+not offer direct support for numeric ranges, which makes the code more complex.
+If you find the code difficult to understand, you may also use multiple `if`
+statements instead of a `case` block.
+
+`case.sh` illustrates two ways of supporting ranges in a `case` statement. The first
+one uses regular expressions (which are divided by the OR operator, a pipe `|`), whereas the second offers ranges through a different approach.
+Each expression such as `(NUM<81)` is evaluated and if it is `true`, the code in the
+respective branch is executed. Notice that the order of the branches is significant because
+only the code from the first match will be executed.
+
+Executing `case.sh` will generate the following output:
+
+ ./case.sh 12
+
+{{< output >}}
+Testing 12
+From 2 to 80
+12 smaller than 80
+{{< /output >}}
+
+If you give `case.sh` a different input, you will get the following output:
+
+ ./case.sh 0
+{{< output >}}
+Testing 0
+Zero!
+0 smaller than 80
+{{< /output >}}
+
+
+## File and Directory Basics
+
+### Working with Files and Directories
+
+One often important operation that you may find yourself needing to perform is specifying
+whether a given file or directory actually exists. This is idea is illustrated in `files.sh`:
+
+{{< file "files.sh" bash >}}
+#!/bin/bash
+
+if [[ $# -le 0 ]]
+then
+ echo Not enough arguments!
+fi
+
+for arg in "$@"
+do
+ # Does it actually exist?
+ if [[ -e "$arg" ]]
+ then
+ echo -n "$arg exists "
+ fi
+
+ # Is it a file or Is it a directory?
+ if [ -f "$arg" ]
+ then
+ echo "and is a regular file!"
+ elif [ -d "$arg" ]
+ then
+ echo "and is a regular directory!"
+ else
+ echo "and is neither a regular file nor a regular directory!"
+ fi
+done
+{{< /file >}}
+
+The `-e` operator will check whether a file exists regardless of its type – this
+is the first test that we are performing. The other two tests use `-f` and `-d`
+for specifying whether we are dealing with a regular file or a directory,
+respectively. Last, the `-le` operator stands for `less than or equal` and is used
+for comparing numeric values.
+
+Executing `files.sh` will generate the following output:
+
+ ./files.sh /tmp aFile /dev/stdin
+
+{{< output >}}
+/tmp exists and is a regular directory!
+aFile exists and is a regular file!
+/dev/stdin exists and is neither a regular file nor a regular directory!
+{{< /output >}}
+
+The following bash script will accept one command line argument, which is a string you'd like to find, and then a list of files that will be searched for that given string. If there is a match, then the filename of the file will appear on the screen.
+
+{{< file "match.sh" bash >}}
+#!/bin/bash
+
+if [[ $# -le 1 ]]
+then
+ echo Usage: $0 string files!
+fi
+
+string=$1
+for arg in "${@:2}"
+do
+ # Does it actually exist?
+ if [[ ! -e "$arg" ]]
+ then
+ echo "* Skipping ${arg}"
+ continue
+ fi
+ # Is it a regular file?
+ if [ -f "$arg" ]
+ then
+ ti=`grep ${string} ${arg} | wc -l`
+ ti=$(($ti + 0))
+ if [[ $ti -gt 0 ]]
+ then
+ echo ${arg}
+ fi
+ else
+ echo "* $arg is not a regular file!"
+ fi
+done
+{{< /file >}}
+
+The `"${@:2}"` notation allows you to skip the first element from the list
+of command line arguments because this is the string that we will be looking for
+in the list of files that follow.
+
+Executing `match.sh` will generate the following output:
+
+ ./match.sh while *.sh /tmp /var/log ./combine.sh doesNotExist
+
+{{< output >}}
+combine.sh
+loops.sh
+* /tmp is not a regular file!
+* /var/log is not a regular file!
+./combine.sh
+* Skipping doesNotExist
+{{< /output >}}
+
+In part 2 of the bash scripting guides you will learn more about working with files and
+directories with the bash scripting language.
+
+## Summary
+
+The scripting language of bash can do many more things than the ones presented in
+this guide. The next part of this guide will present more interesting bash shell
+scripts and shed more light into topics such as working with files and directories,
+the `printf` command, the `select` statement and reading files.
diff --git a/docs/development/python/flask-and-gunicorn-on-ubuntu/LiveApp.png b/docs/development/python/flask-and-gunicorn-on-ubuntu/LiveApp.png
new file mode 100644
index 00000000000..3165740d244
Binary files /dev/null and b/docs/development/python/flask-and-gunicorn-on-ubuntu/LiveApp.png differ
diff --git a/docs/development/python/flask-and-gunicorn-on-ubuntu/badgatewayerr.png b/docs/development/python/flask-and-gunicorn-on-ubuntu/badgatewayerr.png
new file mode 100644
index 00000000000..c2810e48aef
Binary files /dev/null and b/docs/development/python/flask-and-gunicorn-on-ubuntu/badgatewayerr.png differ
diff --git a/docs/development/python/flask-and-gunicorn-on-ubuntu/index.md b/docs/development/python/flask-and-gunicorn-on-ubuntu/index.md
new file mode 100644
index 00000000000..f1538b172a4
--- /dev/null
+++ b/docs/development/python/flask-and-gunicorn-on-ubuntu/index.md
@@ -0,0 +1,322 @@
+---
+author:
+ name: Austin Balarin
+ email: abalarin@linode.com
+description: 'This guide will walk you through the steps to deploy a Flask application to a production environment running on a Linode.'
+keywords: ['python','flask','gunicorn','nginx', 'flask deployment', 'python flask']
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+published: 2019-10-10
+modified: 2019-10-10
+modified_by:
+ name: abalarin
+title: "Deploy a Flask Application on Ubuntu"
+contributor:
+ name: Austin Balarin
+ link: https://github.com/abalarin
+external_resources:
+- '[Python](https://www.python.org/)'
+- '[Flask](https://flask.palletsprojects.com/en/1.0.x/)'
+- '[NGINX](https://www.nginx.com/resources/wiki/)'
+- '[Gunicorn](http://docs.gunicorn.org/en/stable/)'
+---
+Flask is a light-weight web framework for Python that includes several utilities and libraries you can use to create a web application. Once you have developed a Flask application in a local environment, you will need to prepare the application's production environment in order to run the application and serve it to your application's users via the internet.
+
+This guide will walk you through the steps to deploy a Flask application to a production environment running on a Linode. Your production environment will use [NGINX](http://localhost:1313/docs/web-servers/nginx/nginx-installation-and-basic-setup/) as the web server and reverse proxy, [Gunicorn](https://gunicorn.org/) as the web server gateway interface (WSGI) application server, and [Supervisor](http://supervisord.org/) for monitoring and auto-reloading Gunicorn should it go down. This guide will not cover creating a Flask application or related Python concepts.
+
+In this guide you will complete the following:
+
+- [Copy an existing Flask application from a local development environment to a production environment](#copy-your-flask-app-to-your-linode)
+- [Install and configure NGINX](#install-and-configure-nginx)
+- [Configure your Flask application's production environment variables](#configure-flask)
+- [Install and configure Gunicorn](#install-and-configure-gunicorn)
+- [Install and configure Supervisor](#install-and-configure-supervisor)
+
+ {{< disclosure-note "Assumptions">}}
+This guide assumes you are familiar with the following concepts and skills:
+
+* The [Python programming language](https://docs.python.org/3/tutorial/index.html)
+* [Setting up a local virtual environment](https://docs.python-guide.org/dev/virtualenvs/) for Python programming
+* [Creating applications using Flask](https://flask.palletsprojects.com/en/1.1.x/quickstart/#)
+* Using a local and remote version control system, like [Git and GitHub](/docs/quick-answers/linux/how-to-use-git/).
+ {{ disclosure-note >}}
+
+## Before You Begin
+1. [Create a Flask Application](https://flask.palletsprojects.com/en/1.1.x/tutorial/) or use this [Example Blog Application](https://github.com/abalarin/Flask-on-Linode). Clone and run it on your local machine [using GitHub](/docs/quick-answers/linux/how-to-use-git/).
+
+ git clone https://github.com/abalarin/Flask-on-Linode.git flask_app_project
+
+ {{< note >}}
+ The [Example Flask Blog Application](https://github.com/abalarin/Flask-on-Linode) will be used throughout this guide. The application's root directory is `flask_app_project`.
+ {{ note >}}
+
+1. If you're not using the example application, host your Flask application code on a remote version control system, like GitHub. This guide will use GitHub for all examples.
+
+1. [Create a 1GB Linode](/docs/getting-started/#create-a-linode) to host your Flask web application. Depending on the size of your application and the amount of users you expect to visit it, you may consider a large [Linode plan](/docs/platform/how-to-choose-a-linode-plan/).
+
+1. Familiarize yourself with our [Getting Started](/docs/getting-started/) guide and complete the steps for [updating your system's software](/docs/getting-started/#install-software-updates), setting your Linode's [hostname](/docs/getting-started/#set-the-hostname) and [timezone](/docs/getting-started/#set-the-timezone).
+
+1. This guide will use `sudo` wherever possible. Complete the sections of our [Securing Your Server](/docs/security/securing-your-server/) to create a [limited user account](/docs/security/securing-your-server/#add-a-limited-user-account), [harden SSH access](/docs/security/securing-your-server/#harden-ssh-access) and [remove unnecessary network services](/docs/security/securing-your-server/#remove-unused-network-facing-services).
+
+## Copy Your Flask App to Your Linode
+
+After creating your Flask application in your local development environment, you are now ready to deploy it to a production environment. You will need to copy your local Flask application code to your Linode. You can accomplish this by either [cloning your GitHub project to your Linode](#clone-your-app-from-source-control) using Git or by using the [secure copy method](#secure-copy-your-app-from-a-local-machine) to directly transfer your application files to your Linode. This section will provide steps for both options.
+
+{{< note >}}
+This guide's examples will transfer your Flask application files to your Linode's `/home` directory. If you prefer, you can store your application files in a different directory, however, ensure you run the examples using your own app's directory location.
+{{< /note >}}
+
+### Clone Your App From Source Control
+
+1. Ensure your latest Flask application code is available in your project's remote repository.
+
+1. SSH into your Linode. Replace the example IP address with your Linode’s IP address:
+
+ ssh user@192.0.2.0
+
+1. Navigate to your Linode's home directory:
+
+ cd /home
+
+1. Clone your project from your remote version control system. If you are not using the example repository, [Example Flask Blog Application](https://github.com/abalarin/Flask-on-Linode), replace the example repo with your own:
+
+ git clone https://github.com/abalarin/Flask-on-Linode.git flask_app_project
+
+ {{< output >}}
+root@localhost:/home# git clone https://github.com/abalarin/Flask-on-Linode.git
+Cloning into 'Flask-on-Linode'...
+remote: Enumerating objects: 79, done.
+remote: Counting objects: 100% (79/79), done.
+remote: Compressing objects: 100% (57/57), done.
+remote: Total 79 (delta 26), reused 66 (delta 16), pack-reused 0
+Unpacking objects: 100% (79/79), done.
+Checking connectivity... done.
+{{< /output >}}
+
+### Secure Copy your App From a Local Machine
+
+1. From your local machine, secure copy (SCP) your project into your Linode's `/home` directory. Replace the example IP address with your Linode’s IP address and `flask_app` with the name of your project's root directory:
+
+ scp -r flask_app_project/ user@192.0.2.0:/home
+
+1. Once complete, navigate to your Linode and view the contents of your copied directory:
+
+ ls flask_app_project
+
+ You should see a similar output:
+
+ {{< output >}}
+ flask_app FlaskDeployment.md README.md
+ {{ output >}}
+
+ Now that your Linode contains your application files, you can move on to preparing your production environment.
+
+## Prepare Your Production Environment
+### Install and Configure NGINX
+[NGINX](/docs/web-servers/nginx/nginx-installation-and-basic-setup/) is open-source software that can be used as a high-performance web server, reverse proxy, load-balancer, and more. In this section you will configure NGINX as a web server and reverse proxy for your Flask application. This means that NGINX will sit between your Flask application and external clients and forward all client requests to your running Flask application.
+
+1. Install NGINX:
+
+ sudo apt install nginx
+
+2. Using your editor of choice, create an NGINX configuration file for your app with the example content and save it. This example uses the [nano](/docs/quick-answers/linux/use-nano-to-edit-files-in-linux/) text editor. Replace `flask_app` with your applications name and `192.0.2.0` with your Linode's IP or your fully qualified domain name (FQDN):
+
+ sudo nano /etc/nginx/sites-enabled/flask_app
+
+ {{< file "/etc/nginx/sites-enabled/flask_app" nginx >}}
+server {
+ listen 80;
+ server_name 192.0.2.0;
+
+ location / {
+ proxy_pass http://127.0.0.1:8000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+}
+{{< /file >}}
+
+3. Disable the NGINX's default configuration file by removing its symlink:
+
+ sudo unlink /etc/nginx/sites-enabled/default
+
+4. Reload your NGINX configuration file:
+
+ sudo nginx -s reload
+
+5. Navigate to your Linode's IP address in a web browser. You should see a similar NGINX Gateway error. This error appears because you have not set up the WSGI application server yet. You will set up your application server in the [Install and Configure Gunicorn](#install-and-configure-gunicorn) section of the guide.
+
+ 
+
+### Install Python and Packages
+
+To run your Flask application, you will need to install Python, Flask, pip3 and any other required package dependencies on your Linode.
+
+{{< note >}}
+This guide was created using Python 3.6.8
+{{ note >}}
+
+1. In your Linode's `/home` directory, install Python 3:
+
+ sudo apt install python3
+
+1. Install pip3, the standard package manager for Python:
+
+ sudo apt install python3-pip
+
+1. Navigate to your project's root directory:
+
+ cd /home/flask_app_project
+
+1. Install Flask packages and libraries using pip3. If you are using the [Example Flask Blog Application](https://github.com/abalarin/Flask-on-Linode.git), then the packages your application will need are listed in the [`/home/flask_app_project/flask_app/requirements.txt`](https://github.com/abalarin/Flask-on-Linode/blob/master/flask_app/requirements.txt) file. You can use pip to install all listed packages.
+
+ pip3 install -r flask_app/requirements.txt
+
+ While the packages and libraries are being installed, you will see a similar output:
+ {{< output >}}
+root@localhost:/home/Flask-on-Linode# pip3 install -r flask_app/requirements.txt
+Collecting flask-sqlalchemy (from -r flask_app/requirements.txt (line 1))
+ Downloading https://files.pythonhosted.org/packages/08/ca/582442cad71504a1514a2f053006c8bb128844133d6076a4df17117545fa/Flask_SQLAlchemy-2.4.0-py2.py3-none-any.whl
+Collecting sqlalchemy (from -r flask_app/requirements.txt (line 2))
+ Downloading https://files.pythonhosted.org/packages/55/98/56b7155bab287cd0c78dee26258835db36e91f2efef41f125ed6f6f1f334/SQLAlchemy-1.3.6.tar.gz (5.9MB)
+ 100% |████████████████████████████████| 5.9MB 218kB/s
+Collecting flask-security (from -r flask_app/requirements.txt (line 3))
+ Downloading https://files.pythonhosted.org/packages/88/47/4908a5040120768ff4fb2465c7eeafeb9239c27d2919bd67c4ccc1b43e14/Flask_Security-3.0.0-py2.py3-none-any.whl (68kB)
+ 100% |████████████████████████████████| 71kB 8.7MB/s
+Collecting flask-wtf (from -r flask_app/requirements.txt (line 4))
+ Downloading https://files.pythonhosted.org/packages/60/3a/58c629472d10539ae5167dc7c1fecfa95dd7d0b7864623931e3776438a24/Flask_WTF-0.14.2-py2.py3-none-any.whl
+...
+{{< /output >}}
+
+ Now that your Linode has all required dependencies, you will configure Flask in the next section.
+
+### Configure Flask
+Depending on your Flask application's environment, there are different settings you may need to configure, like toggling the debug mode, setting the secret key, setting the database URI, etc. For more information on Flask's available configuration options see Flask's [configuration docs](https://flask.palletsprojects.com/en/1.1.x/config/#builtin-configuration-values).
+
+In this section, you will create a JSON file to store your environment configurations and then load that configuration into your Flask app. The configuration created in this section is a basic example of some Flask environment variables you might include in your application.
+
+{{< caution >}}
+You should keep sensitive configuration files **outside of source control**. If you source control your configuration file, which contains sensitive values, in a remote repository, then someone could access it and use that information to compromise your Linode or application. To keep your configuration file out of your Git repository, add it to your `.gitignore` file.
+{{< /caution >}}
+
+1. Create a JSON configuration file with the text editor of your choice:
+
+ sudo nano /etc/config.json
+
+1. Store your application's environment variables in your JSON configuration file with the example content:
+
+ {{< file "/etc/config.json" json >}}
+{
+ "SECRET_KEY": "1A37BbcCJh67",
+ "SQLALCHEMY_DATABASE_URI": "sqlite:///site.db"
+}
+{{< /file >}}
+
+ - The `SECRET_KEY` is used to keep client-side sessions secure using a session cookie that can only be modified if the secret key is known and used for signing. Replace the value included in the example with your own randomly generated value.
+
+ - The `SQLALCHEMY_DATABASE_URI` defines the database URI that should be used for the application's connection to SQLite.
+
+2. Modify your Flask app's `__init__.py` file to import the newly created JSON configuration:
+
+ {{< file "/home/flask_app_project/flask_app/__init__.py" python >}}
+from flask import Flask
+from flask_sqlalchemy import SQLAlchemy
+from flask_login import LoginManager
+import json
+import urllib3
+
+app = Flask(__name__)
+
+with open('/etc/config.json') as config_file:
+ config = json.load(config_file)
+
+app.config['SECRET_KEY'] = config.get('SECRET_KEY')
+app.config['SQLALCHEMY_DATABASE_URI'] = config.get('SQLALCHEMY_DATABASE_URI')
+db = SQLAlchemy(app)
+
+login_manager = LoginManager()
+login_manager.init_app(app)
+
+from flask_app import routes
+ {{ file >}}
+
+### Install and Configure Gunicorn
+[Gunicorn](https://gunicorn.org/), *Green Unicorn*, is a Python web server gateway interface (WSGI) HTTP Server for UNIX. It will be used to forward requests from your NGINX web server to your Flask application.
+
+1. Install Gunicorn on your Linode:
+
+ sudo apt install gunicorn3
+
+2. Run Gunicorn from your application's root directory, `flask_app_project`. The command tells Gunicorn to look for the WSGI instance named **app** in the **flask_app** directory. In our example project, the WSGI instance named **app** is located in [`/home/Flask-on-Linode/flask_app/__init__.py`](https://github.com/abalarin/Flask-on-Linode/blob/master/flask_app/__init__.py).
+
+ gunicorn3 --workers=3 flask_app:app
+
+ {{< output >}}
+root@localhost:/home/Flask-on-Linode# gunicorn -w 3 flask_app:app
+[2019-07-25 15:09:04 +0000] [32421] [INFO] Starting gunicorn 19.9.0
+[2019-07-25 15:09:04 +0000] [32421] [INFO] Listening at: http://127.0.0.1:8000 (32421)
+[2019-07-25 15:09:04 +0000] [32421] [INFO] Using worker: sync
+[2019-07-25 15:09:04 +0000] [32424] [INFO] Booting worker with pid: 32424
+[2019-07-25 15:09:04 +0000] [32425] [INFO] Booting worker with pid: 32425
+[2019-07-25 15:09:04 +0000] [32426] [INFO] Booting worker with pid: 32426
+{{< /output >}}
+
+ {{< note >}}
+You can specify the amount of workers you want Gunicorn to use with the `--workers` flag. A good rule of thumb to determine [worker](http://docs.gunicorn.org/en/stable/design.html#server-model) count is to double your system's CPU cores and add 1. For a Nanode with 1 CPU core you should use 3 workers.
+{{< /note >}}
+
+1. After running Gunicorn, your Flask application should be live and available over the internet. Open a web browser and enter your Linode's IP address to access your application. If you used the example Flask blog application, you should see the following:
+
+ 
+
+ Continue on to the next section to configure Supervisor to monitor and control your Flask app.
+
+### Install and Configure Supervisor
+[Supervisor](http://supervisord.org/) is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems. Supervisor can handle auto-reloading Gunicorn if it crashes or if your Linode is rebooted unexpectedly. In this section, you will install and configure Supervisor.
+
+1. Open a new shell session and SSH into your Linode:
+
+ ssh user@192.0.2.0
+
+1. Install Supervisor:
+
+ sudo apt install supervisor
+
+2. Create a Supervisor script. Replace any instances of `flask_app` with the name of your application:
+
+ sudo nano /etc/supervisor/conf.d/flask_app.conf
+
+ {{< file "/etc/supervisor/conf.d/flask_app.conf" supervisor >}}
+[program:flask_app]
+directory=/home/flask_app_project
+command=gunicorn3 -workers=3 flask_app:app
+autostart=true
+autorestart=true
+stopasgroup=true
+killasgroup=true
+stderr_logfile=/var/log/flask_app/flask_app.err.log
+stdout_logfile=/var/log/flask_app/flask_app.out.log
+{{< /file >}}
+
+3. Create the log directories and files listed in the `flask_app.conf` file. Make sure to replace `flask_app` if it was modified in the Supervisor script above:
+
+ sudo mkdir /var/log/flask_app
+ sudo touch /var/log/flask_app/flask_app.out.log
+ sudo touch /var/log/flask_app/flask_app.err.log
+
+4. Reload Supervisor to apply your changes:
+
+ sudo supervisorctl reload
+
+ You should see a similar output:
+ {{< output >}}
+Restarted supervisord
+ {{< /output >}}
+
+ {{< note >}}
+Your application should now be accessible again via your Linode's IP. If you are unable to access your application or receive a bad gateway error, Gunicorn is likely not running. Check your log files to further investigate the issue.
+
+ cat /var/log/flaskapp/flaskapp.err.log
+ cat /var/log/flaskapp/flaskapp.out.log
+ {{ note >}}
+
+ Your Flask application is now deployed to your production environment and available to anyone for viewing. You can follow a similar workflow to deploy any Flask application to a Linode.
diff --git a/docs/email/running-a-mail-server/index.md b/docs/email/running-a-mail-server/index.md
index d887ef5d501..7926493554f 100644
--- a/docs/email/running-a-mail-server/index.md
+++ b/docs/email/running-a-mail-server/index.md
@@ -7,7 +7,6 @@ og_description: 'Take control of your email with your own mail server. This guid
keywords: ["mail server", "linode guide", "running a mail server", "Self-host Mail"]
license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
aliases: ['mailserver/']
-modified: 2019-01-07
modified_by:
name: Linode
published: 2013-06-05
@@ -52,11 +51,11 @@ If the prospect of managing your own mail server is too daunting, you should con
There are several third-party mail services available:
-- [Fastmail](https://www.fastmail.fm)
-- [Google Apps](http://www.google.com/intl/en/enterprise/apps/business/) uses the familiar Gmail interface. Check out our guide to [using Google Apps with your Linode](/docs/email/google-mail).
-- [Office 365](https://login.microsoftonline.com/) is the successor to Outlook.com and can support custom domains for email, amongst other services.
+- [Fastmail](https://www.fastmail.com)
+- [Google Apps](http://www.google.com/intl/en/enterprise/apps/business/) uses the familiar Gmail interface. Check out our guide to [using Google Apps with your Linode](/docs/email/using-google-apps-for-email/).
+- [Office 365](https://www.office.com) is the successor to Outlook.com and can support custom domains for email, amongst other services.
-If you decide to use an outside mail service, you will still need to set up [DNS](/docs/networking/dns/dns-manager) for your mail and use the settings provided by the third-party mail service.
+If you decide to use an outside mail service, you will still need to set up [DNS](/docs/platform/manager/dns-manager/) for your mail and use the settings provided by the third-party mail service.
## How Mail Servers Work
@@ -92,7 +91,7 @@ Here are the most popular MTA services available:
- [Courier Mail Server](http://www.courier-mta.org) comes with Courier-IMAP, which is the popular part of the Courier mail server suite, but Courier-MTA also includes mail relaying features. It's a simpler MTA but somewhat limited.
- [Exim](http://www.exim.org) is modern and oriented towards flexibility. It's secure, but not quite as security-oriented as Postfix. It's very customizable, but is one of the most complex MTAs to configure.
- [Postfix](http://www.postfix.org) is part of Linode's [recommended mail server build](/docs/email/postfix/email-with-postfix-dovecot-and-mysql). It's modern, security-oriented, and very flexible. It is slightly simpler to set up than Exim.
-- [Qmail](http://www.qmail.org/top.html) is a modern MTAs and supports [Maildir-style](https://en.wikipedia.org/wiki/Maildir) directories. Qmail has not received an update since 2007, but remains very popular.
+- [Qmail](http://cr.yp.to/qmail.html) is a modern MTAs and supports [Maildir-style](https://en.wikipedia.org/wiki/Maildir) directories. Qmail has not received an update since 2007, but remains very popular.
- [Sendmail](http://www.sendmail.com/sm/open_source/) is a legacy MTA that has a large following and good support.
- [Zimbra](http://www.zimbra.com) is an all-in-one mail service. Zimbra offers a simple install, but few configurable options.
@@ -102,7 +101,7 @@ MDAs move email from the MTA's queue to individual mailbox directories within yo
These are some of the most popular MDAs available:
-- [Cyrus's MDA](http://www.cyrusimap.org/index.php) is part of the Cyrus IMAP/POP3 server. Cyrus is a modern, security-oriented IMAP/POP3 server designed to run on servers where users do not log in directly.
+- [Cyrus's MDA](https://www.cyrusimap.org) is part of the Cyrus IMAP/POP3 server. Cyrus is a modern, security-oriented IMAP/POP3 server designed to run on servers where users do not log in directly.
- [Deliver](http://linux.die.net/man/8/deliver) is a simple Linux mail delivery utility that is configured in the Imapd configuration files by default.
- [Dovecot's LDA](http://wiki2.dovecot.org/LDA) and [Dovecot's LMTP server](http://wiki2.dovecot.org/LMTP) are part of the Dovecot IMAP/POP3 server. Dovecot is a lightweight, modern, and configurable mail server.
- [maildrop](http://www.courier-mta.org/maildrop/) is Courier's MDA. Courier is an all-in-one mail server.
@@ -119,9 +118,9 @@ Here are the most popular IMAP and POP3 servers available:
- [Citadel](http://www.citadel.org) is an all-in-one mail service that includes mail, calendars, instant messaging, mailing lists, and other collaboration tools. It's open source and geared towards small and medium-sized organizations. Linode has guides for [Citadel on Ubuntu 12.04](/docs/email/citadel/email-with-citadel-on-ubuntu-12-04-lts-precise-pangolin/) and [Citadel on Debian 6](/docs/email/citadel/email-with-citadel-on-debian-6-squeeze/).
- [Courier](http://www.courier-mta.org) has a very popular IMAP server called [Courier IMAP](http://www.courier-mta.org/imap/). It's an all-in-one mail server software suite, but Courier IMAP can be installed by itself if that's the only part you need.
-- [Cyrus](http://www.cyrusimap.org/index.php) is a modern, security-oriented IMAP/POP3 server designed to work on sealed servers where users do not log in directly.
+- [Cyrus](https://www.cyrusimap.org) is a modern, security-oriented IMAP/POP3 server designed to work on sealed servers where users do not log in directly.
- [DBMail](http://www.dbmail.org) is an open source project that stores mail in databases instead of flat files.
-- [Dovecot](http://www.dovecot.org) is a lightweight, modern, and configurable mail server, and is part of our [recommended mail server build](/docs/email/postfix/email-with-postfix-dovecot-and-mysql/).
+- [Dovecot](http://dovecot.org) is a lightweight, modern, and configurable mail server, and is part of our [recommended mail server build](/docs/email/postfix/email-with-postfix-dovecot-and-mysql/).
- [Xmail](http://www.xmailserver.org) is a full-featured POP3 server, but does not support IMAP.
- [Zimbra](http://www.zimbra.com) is an all-in-one mail service that's much simpler to install than other options, but less customizable.
@@ -191,7 +190,7 @@ If your Linode is the only mail server you use, you should be able to use the ex
example.com 86400 TXT "v=spf1 a ~all"
{{< /output >}}
-Make sure your SPF records are not too strict. If you accidentally exclude a legitimate mail server, its messages could get marked as spam. Visit [openspf.org](http://www.openspf.org/SPF_Record_Syntax) to learn how SPF records work and how to construct one that works for your setup. Their [examples](http://www.openspf.org/FAQ/Examples) are also helpful.
+Make sure your SPF records are not too strict. If you accidentally exclude a legitimate mail server, its messages could get marked as spam. Visit [open-spf.org](http://www.open-spf.org/SPF_Record_Syntax/) to learn how SPF records work and how to construct one that works for your setup. Their [examples](http://www.open-spf.org/FAQ/Examples/) are also helpful.
#### Reverse DNS
@@ -252,7 +251,7 @@ If you're using a firewall, be sure to edit the rules for your mail server's por
### Webmail
-Webmail is a type of mail client that can be installed on your server and accessed from a web browser. It allows your users to access their email from your website (example: `http://example.com/mail`) anywhere they have access to the internet. Running a web server is a prerequisite for running a webmail client, so follow the [Hosting a Website](/docs/hosting-website) guide if you want to run webmail on your Linode, in addition to installing a mail server.
+Webmail is a type of mail client that can be installed on your server and accessed from a web browser. It allows your users to access their email from your website (example: `http://example.com/mail`) anywhere they have access to the internet. Running a web server is a prerequisite for running a webmail client, so follow the [Hosting a Website](/docs/websites/set-up-web-server-host-website/) guide if you want to run webmail on your Linode, in addition to installing a mail server.
Here are some of the most popular webmail clients:
diff --git a/docs/networking/vpn/set-up-wireguard-vpn-on-debian/index.md b/docs/networking/vpn/set-up-wireguard-vpn-on-debian/index.md
index b942861a173..c9eedf942ab 100644
--- a/docs/networking/vpn/set-up-wireguard-vpn-on-debian/index.md
+++ b/docs/networking/vpn/set-up-wireguard-vpn-on-debian/index.md
@@ -47,13 +47,16 @@ In this guide you will learn how to:
Do not use WireGuard for critical applications. The project is still undergoing security testing and is likely to receive frequent major updates in the future.
{{< /caution >}}
-
## Before You Begin
- [Deploy a Linode](/docs/getting-started/#create-a-linode) running Debian 9.
- [Add a limited user account](/docs/security/securing-your-server/#add-a-limited-user-account) with `sudo` privileges to your Linode.
- Set your system's [hostname](/docs/getting-started/#set-the-hostname).
+{{< note >}}
+The `GRUB 2` kernel is required for this guide. All distributions for all new Linodes now boot with the `GRUB 2` kernel by default. However, if you are running an older distribution, you will need to check to see which kernel you are running. You can use the [Update Kernel Guide](/docs/platform/update-kernel/) to check your kernel version and change it using the Cloud Manager. Select `GRUB 2` from the *Boot Settings: Select a Kernel* dropdown menu in Step 4 of [Update Your Linode Kernel with Linode's Cloud Manager](/docs/platform/update-kernel/#update-your-linode-kernel-with-linode-s-cloud-manager).
+{{< /note >}}
+
## Install WireGuard
1. Add the WireGuard repository to your sources list. Apt will automatically update the package cache.
diff --git a/docs/networking/vpn/set-up-wireguard-vpn-on-ubuntu/index.md b/docs/networking/vpn/set-up-wireguard-vpn-on-ubuntu/index.md
index d53478ba517..233a232d012 100644
--- a/docs/networking/vpn/set-up-wireguard-vpn-on-ubuntu/index.md
+++ b/docs/networking/vpn/set-up-wireguard-vpn-on-ubuntu/index.md
@@ -27,12 +27,14 @@ This guide will configure a simple peer connection between a Linode running Ubun
Do not use WireGuard for critical applications. The project is still undergoing security testing and is likely to receive frequent critical updates in the future.
{{< /caution >}}
-
## Before You Begin
- You will need root access to your Linode, or a user account with `sudo` privilege.
- Set your system's [hostname](/docs/getting-started/#set-the-hostname).
+{{< note >}}
+The `GRUB 2` kernel is required for this guide. All distributions for all new Linodes now boot with the `GRUB 2` kernel by default. However, if you are running an older distribution, you will need to check to see which kernel you are running. You can use the [Update Kernel Guide](/docs/platform/update-kernel/) to check your kernel version and change it using the Cloud Manager. Select `GRUB 2` from the *Boot Settings: Select a Kernel* dropdown menu in Step 4 of [Update Your Linode Kernel with Linode's Cloud Manager](/docs/platform/update-kernel/#update-your-linode-kernel-with-linode-s-cloud-manager).
+{{< /note >}}
## Install WireGuard
diff --git a/docs/platform/disk-images/linode-images/images-create-linode-from-image-small.png b/docs/platform/disk-images/linode-images/images-create-linode-from-image-small.png
index 4964e3e7ce5..fd6c6d4f6c5 100644
Binary files a/docs/platform/disk-images/linode-images/images-create-linode-from-image-small.png and b/docs/platform/disk-images/linode-images/images-create-linode-from-image-small.png differ
diff --git a/docs/platform/disk-images/linode-images/index.md b/docs/platform/disk-images/linode-images/index.md
index 9b2c987e26b..06f0a98f7bd 100644
--- a/docs/platform/disk-images/linode-images/index.md
+++ b/docs/platform/disk-images/linode-images/index.md
@@ -38,6 +38,10 @@ While an image can be captured while your Linode is running, we would recommend

+ {{< caution >}}
+CoreOS disk images are in RAW format. Images made from CoreOS disks will not be able to be used to deploy new Linodes.
+{{< /caution >}}
+
1. Once you click the **Create** button, your image will be frozen for later use. You can view the progress under the bell notifications at the top of the page.

@@ -71,6 +75,9 @@ Deploying one of your saved images to any Linode under your account is a simple
[](images-create-linode-from-image.png)
+ {{< caution >}}
+You cannot deploy an image that was created from a RAW disk format. Attempting to do so will result in a failure.
+{{< /caution >}}
1. Select your desired Region, Linode Plan, Label, and set your root password, then click **Create** to create a Linode with your saved image.
diff --git a/docs/platform/disk-images/resizing-a-linode/disk-allocator.png b/docs/platform/disk-images/resizing-a-linode/disk-allocator.png
index 528be3e3d07..35969b63f41 100644
Binary files a/docs/platform/disk-images/resizing-a-linode/disk-allocator.png and b/docs/platform/disk-images/resizing-a-linode/disk-allocator.png differ
diff --git a/docs/platform/disk-images/resizing-a-linode/index.md b/docs/platform/disk-images/resizing-a-linode/index.md
index 884e9aaf56b..cd61c0967eb 100644
--- a/docs/platform/disk-images/resizing-a-linode/index.md
+++ b/docs/platform/disk-images/resizing-a-linode/index.md
@@ -39,20 +39,15 @@ Here's how to resize your Linode:
[](resize-tab.png)
-1. Select a plan and click the **Submit** button. Your Linode will be powered off and moved to another host. Depending on the size of your Linode, this process can take up to one hour.
-
- Your Linode's main disk will automatically be resized if the following two criteria are met:
+1. You can automatically resize your primary disk by selecting the **Auto Resize Disk** checkbox. This option is not available if you are resizing to a smaller plan and have a disk greater in size than the target plan allows. In that case, you must delete resize your disk before selecting a new plan. Additionally, your disks must be of type `ext 4`,`ext 3`, or `swap`.
- 1. The destination plan has a larger amount of disk space than the current plan. For example, if you are upgrading from a 2 GB to a 4 GB Linode plan.
- 1. The Linode's disk configuration is simple:
- - 1 disk of type `ext 4` or `ext 3` and 1 disk of type `swap` **OR**
- - 1 disk of type `ext 4` or `ext 3`
+ [](resize-auto-checkbox.png)
- If your Linode does not fulfill the above criteria, you will have to manually reallocate un-used storage to your disks, if desired. See the following step for instructions.
+1. Select a plan and click the **Submit** button. Your Linode will be powered off and moved to another host. Depending on the size of your Linode, this process can take up to one hour.
1. (Optional) When the migration completes, check your disk storage allocation meter. If you resized your Linode to a larger plan and the main disk was not automatically resized, you'll have additional un-used storage to allocate to your disks. You may want to add some of this storage to one of your disks if the internal filesystem on it is running low on free space, or just so you can use it in the future.
- Navigate to your Linode's **Settings** tab and expand the **Advanced Configurations** section to view your disk storage allocation meter. Click on the **more options** link (...) next to the disk you'd like to allocate the extra storage to and select **Resize**.
+ Navigate to your Linode's **Advanced** tab to view your disk storage allocation meter. Click on the **more options** link (...) next to the disk you'd like to allocate the extra storage to and select **Resize**.
[](disk-allocator.png)
diff --git a/docs/platform/disk-images/resizing-a-linode/resize-advanced-tab.png b/docs/platform/disk-images/resizing-a-linode/resize-advanced-tab.png
new file mode 100644
index 00000000000..bcd2f9eafd3
Binary files /dev/null and b/docs/platform/disk-images/resizing-a-linode/resize-advanced-tab.png differ
diff --git a/docs/platform/disk-images/resizing-a-linode/resize-auto-checkbox.png b/docs/platform/disk-images/resizing-a-linode/resize-auto-checkbox.png
new file mode 100644
index 00000000000..68927fa823b
Binary files /dev/null and b/docs/platform/disk-images/resizing-a-linode/resize-auto-checkbox.png differ
diff --git a/docs/platform/disk-images/resizing-a-linode/resize-disk.png b/docs/platform/disk-images/resizing-a-linode/resize-disk.png
index ef328077b75..3fe43b6c320 100644
Binary files a/docs/platform/disk-images/resizing-a-linode/resize-disk.png and b/docs/platform/disk-images/resizing-a-linode/resize-disk.png differ
diff --git a/docs/platform/disk-images/resizing-a-linode/resize-tab.png b/docs/platform/disk-images/resizing-a-linode/resize-tab.png
index dd1fbd7f045..0c686b04f31 100644
Binary files a/docs/platform/disk-images/resizing-a-linode/resize-tab.png and b/docs/platform/disk-images/resizing-a-linode/resize-tab.png differ
diff --git a/docs/platform/longview/longview-app-for-mysql/index.md b/docs/platform/longview/longview-app-for-mysql/index.md
index 860e6dd7089..6d72af224ad 100644
--- a/docs/platform/longview/longview-app-for-mysql/index.md
+++ b/docs/platform/longview/longview-app-for-mysql/index.md
@@ -50,6 +50,10 @@ If you receive a failure message or the popup shown below, you should visit the
### Manual Configuration (All Distributions)
+{{< note >}}
+You cannot configure the location of a socket for the Longview client.
+{{< /note >}}
+
To enable the MySQL Longview app manually, follow these steps on your Linode via SSH:
1. Create a new MySQL user with minimal privileges for Longview. Run the following queries on your database as the root MySQL user to create the new user:
diff --git a/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info1.png b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info1.png
new file mode 100644
index 00000000000..17b4a786324
Binary files /dev/null and b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info1.png differ
diff --git a/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info2.png b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info2.png
new file mode 100644
index 00000000000..d84fa686a60
Binary files /dev/null and b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info2.png differ
diff --git a/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info3.png b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info3.png
new file mode 100644
index 00000000000..0cde85b6bdc
Binary files /dev/null and b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-bucket-info3.png differ
diff --git a/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-upload-prompt.png b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-upload-prompt.png
new file mode 100644
index 00000000000..d90cbaca7d3
Binary files /dev/null and b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-upload-prompt.png differ
diff --git a/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-view-files.png b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-view-files.png
new file mode 100644
index 00000000000..4232b715f9f
Binary files /dev/null and b/docs/platform/object-storage/bucket-versioning/bucket-versioning-cyberduck-view-files.png differ
diff --git a/docs/platform/object-storage/bucket-versioning/index.md b/docs/platform/object-storage/bucket-versioning/index.md
new file mode 100644
index 00000000000..41c474e11cb
--- /dev/null
+++ b/docs/platform/object-storage/bucket-versioning/index.md
@@ -0,0 +1,258 @@
+---
+author:
+ name: Linode Community
+ email: docs@linode.com
+description: 'How to use bucket versioning with Linode Object Storage to track and saves changes to your objects.'
+keywords: ['object','storage','bucket','version','versioning']
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+published: 2019-10-14
+modified_by:
+ name: Linode
+title: "Bucket Versioning with Linode Object Storage"
+contributor:
+ name: Linode
+external_resources:
+ - '[AWS CLI S3 API command reference](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html)'
+---
+
+{{< note >}}
+[Linode Object Storage](/docs/platform/object-storage/) is currently in a closed early access Beta, and you may not have access to Object Storage through the Cloud Manager or other tools. To request access to the Early Access Program (EAP), [open up a Customer Support ticket](/docs/platform/billing-and-support/support/#contacting-linode-support) or e-mail objbeta@linode.com. Beta access is completely free.
+
+Because Object Storage is in Beta, there may be breaking changes to how you access and manage Object Storage. This guide will be updated to reflect these changes if and when they occur. To view the changes that happen to this guide over time, visit the [source text for it on GitHub](https://github.com/linode/docs/blob/master/docs/platform/object-storage/bucket-versioning/index.md).
+{{ note >}}
+
+Linode Object Storage allows for bucket versioning so that you can retain different versions of your objects within buckets. This makes it easy to save older versions of objects, as well as quickly revert to an object's previous state.
+
+In this guide, you will learn about:
+
+- [Bucket versioning](/docs/platform/object-storage/bucket-versioning/#bucket-versioning) concepts.
+- How to use the [graphical user interface (GUI) Cyberduck](/docs/platform/object-storage/bucket-versioning/#cyberduck) client to version buckets.
+- How to version buckets from the [AWS command line interface (CLI)](/docs/platform/object-storage/bucket-versioning/#aws-cli), which is compatible with Linode Object Storage.
+
+## Before You Begin
+
+You should familiarize yourself with the basics of Linode Object Storage by reading the [How to Use Linode Object Storage](/docs/platform/object-storage/how-to-use-object-storage/) guide.
+
+You'll also need to have a bucket with which you want to enable bucket versioning. Follow the [Create a Bucket](/docs/platform/object-storage/how-to-use-object-storage/#create-a-bucket) section of the How to Use Linode Object Storage guide if you do not already have one.
+
+## Bucket Versioning
+
+Bucket versioning works by saving separate versions of objects in a bucket. When bucket versioning is enabled, an object that is uploaded to a bucket won't overwrite a previous copy of that object. Instead, each version of the object is given a different ID number and saved.
+
+When attempting to view the object over HTTP or to download the object without supplying a version ID, the latest version of the object is returned. If you delete an object with bucket versioning enabled, a delete marker is inserted into the bucket to report that the object has been deleted, but the bucket will retain all previous versions of the object. Any further retrieval operations will return the most recent version of an object.
+
+{{< caution >}}
+Every version of an object counts towards the monthly billable storage quota. While saving a few revisions is probably not something to worry about, large version controlled buckets with many thousands of objects will see a noticeable increase in storage space demands, and should be monitored carefully.
+{{ caution >}}
+
+### Cyberduck
+
+Cyberduck is a GUI application that supports a wide variety of file transfer protocols, including S3-compatible Object Storage. For basic Cyberduck functionality, such as creating buckets and uploading objects, consult our [How to Use Linode Object Storage](/docs/platform/object-storage/how-to-use-object-storage/#cyberduck) guide.
+
+{{< note >}}
+If you don't have Cyberduck set up on your computer, visit the [Install and Configure Cyberduck](/docs/platform/object-storage/how-to-use-object-storage/#install-and-configure-cyberduck) of the How to Use Linode Object Storage guide.
+{{< /note >}}
+
+To use bucket versioning with Cyberduck:
+
+1. Enable bucket versioning for your bucket. Right-click or control-click on the bucket and select **Info** from the bucket's context menu, or select **File > Info** from the menu bar.
+
+ [](bucket-versioning-cyberduck-bucket-info1.png)
+
+1. A settings menu will appear. Select the **S3** menu heading.
+
+ [](bucket-versioning-cyberduck-bucket-info2.png)
+
+1. In the **Versioning** section, check the checkbox labeled **Bucket Versioning**.
+
+ [](bucket-versioning-cyberduck-bucket-info3.png)
+
+1. Your bucket will now retain previous versions of the objects within it. To test this functionality, create an example text document on your computer and add some text to it:
+
+ {{< file "test.txt" >}}
+This is version 1 of the object.
+{{ file >}}
+
+ Upload this file to your bucket by dragging it into Cyberduck, or by selecting **File > Upload** from the menu bar.
+
+1. Now, edit the same file on your computer and make a small change. We will use this change to demonstrate bucket versioning.
+
+ {{< file "test.txt" >}}
+This is version 2 of the object.
+{{ file >}}
+
+ Save the change and upload the file to your bucket just as you did in the previous step. Cyberduck will prompt you this time to confirm that you'd like to upload the file. Though the dropdown menu says **Overwrite**, the file will not be overwritten.
+
+ [](bucket-versioning-cyberduck-upload-prompt.png)
+
+1. You now have two objects in your bucket, though initially you may only see one. To view the different saved versions of your object, select **View** from the menu bar and click on **Show Hidden Files**.
+
+ You should now see two files in your bucket, with the hidden file that you've just revealed being grayed-out. This grayed-out file is the older version of the file that you uploaded first.
+
+ {{< note >}}
+You may have to click the **Refresh** button in Cyberduck's toolbar to see the hidden files.
+{{< /note >}}
+
+ [](bucket-versioning-cyberduck-view-files.png)
+
+1. Double click the grayed-out version of the file (the one with the earlier modified date) to download the file. Once opened, you'll see that the file contains the contents of the first revision.
+
+1. To revert to a previous file revision, right-click or control-click on an object and select **Revert**. This will create a new object in the bucket, preserving the state of the previous two objects. At this point the current object will contain the contents of revision one, the second object will contain the contents of revision two, and the third object will contain to the contents of revision one. You can see, then, how bucket versioning works to maintain a stateful history.
+
+ {{< note >}}
+Each file has its own permissions. If you'd like to view objects via HTTP, then you'll need to manually set the permissions for each object to *Everyone* each time you upload or revert to a different version of the object, as described in the [How to Use Linode Object Storage](/docs/platform/object-storage/how-to-use-object-storage/#upload-download-and-delete-an-object-with-cyberduck) guide.
+{{ note >}}
+
+### AWS CLI
+
+Because Linode Object Storage is compatible with S3, several tools that are designed to work with S3 can be adapted to Linode Object Storage, like the AWS CLI.
+
+{{< disclosure-note "Installing the AWS CLI" >}}
+The AWS CLI can be installed using [pip](https://pip.pypa.io/en/stable/), the Python package manager, on macOS and Linux:
+
+ pip install awscli
+
+If you are using Windows, you can download the CLI by visiting the [AWS CLI homepage](https://aws.amazon.com/cli/).
+
+You'll need to configure the AWS CLI before you can use it. To do so, run the configure command:
+
+ aws configure
+
+You'll be prompted to enter your AWS access key and AWS secret access key, but you can enter your Linode access key and Linode secret access key here instead. You can leave the other fields blank.
+{{< /disclosure-note >}}
+
+To use bucket versioning with the AWS CLI:
+
+1. Turn on bucket versioning with the `put-bucket-versioning` command. Supply the Linode Object Storage endpoint and bucket name to the this command. In the below example, the bucket is named `bucket-versioning-example`:
+
+ aws s3api put-bucket-versioning --endpoint=http://us-east-1.linodeobjects.com --bucket=bucket-versioning-example --versioning-configuration Status=Enabled
+
+1. The above command won't prompt any response. To check on the status of bucket-versioning, issue the `get-bucket-versioning` command, again supplying the Linode Object Storage endpoint and your bucket name:
+
+ aws s3api get-bucket-versioning --endpoint=http://us-east-1.linodeobjects.com --bucket=bucket-versioning-example
+
+ You should see output like the following:
+
+ {{< output >}}
+{
+ "Status": "Enabled",
+ "MFADelete": "Disabled"
+}
+{{< /output >}}
+
+ Here you can see that bucket versioning has been successfully applied to the bucket because the `Status` is set to `Enabled`.
+
+1. To test bucket versioning, create an example text document on your computer and add some text to it:
+
+ {{< file "test.txt" >}}
+This is version 1 of the file.
+{{ file >}}
+
+1. Upload the file to your bucket using the `put-object` command, again supplying the Linode Object Storage endpoint and your bucket name:
+
+ aws s3api put-object --endpoint=http://us-east-1.linodeobjects.com --bucket=bucket-versioning-example --key test.txt --body test.txt
+
+ In the above command, the `key` is the name you would like to give the object after it is uploaded, and the `body` is the local filename of the object. These can be different.
+
+ {{< note >}}
+When retrieving the file you will need to give the object's `key` rather than it's local filename.
+{{< /note >}}
+
+1. You should see output like the following:
+
+ {{< output >}}
+{
+ "ETag": "\"9a7b64c98b066602b21f869ae7cd673a\"",
+ "VersionId": "4ACJQUNQ1ORV2oZ1SRE7l2M7nTjD1pv"
+}
+{{< /output >}}
+
+ Take note of the `VersionId`, which will be referenced later.
+
+1. Now, modify the local file to indicate that this file is a different version than the one you previously uploaded:
+
+ {{< file "test.txt" >}}
+This is version 2 of the file.
+{{ file >}}
+
+1. Upload the modified version of the file to Object Storage:
+
+ aws s3api put-object --endpoint=http://us-east-1.linodeobjects.com --bucket=bucket-versioning-example --key test.txt --body test.txt
+
+ You should see output like the following:
+
+ {{< output >}}
+{
+ "ETag": "\"38b0d2ff1c03df82aea67222983d337e\"",
+ "VersionId": "cdw7Lz4CPdm3wAJwBIJ6NhOUDqZo-Y7"
+}
+{{< /output >}}
+
+ Note that the `VersionId` has changed to reflect the newer version of the object.
+
+1. You now have two versions of the object in your bucket. To view these objects, use the `list-object-versions` command:
+
+ aws s3api list-object-versions --endpoint=http://us-east-1.linodeobjects.com --bucket=bucket-versioning-example
+
+ You should see output like the following:
+
+ {{< output >}}
+{
+ "Versions": [
+ {
+ "ETag": "\"38b0d2ff1c03df82aea67222983d337e\"",
+ "Size": 6,
+ "StorageClass": "STANDARD",
+ "Key": "test.txt",
+ "VersionId": "cdw7Lz4CPdm3wAJwBIJ6NhOUDqZo-Y7",
+ "IsLatest": true,
+ "LastModified": "2019-09-18T11:51:33.070Z",
+ "Owner": {
+ "DisplayName": "a9354920-007a-4480-9271-06d3ff7f8426",
+ "ID": "a9354920-007a-4480-9271-06d3ff7f8426"
+ }
+ },
+ {
+ "ETag": "\"9a7b64c98b066602b21f869ae7cd673a\"",
+ "Size": 6,
+ "StorageClass": "STANDARD",
+ "Key": "test.txt",
+ "VersionId": "4ACJQUNQ1ORV2oZ1SRE7l2M7nTjD1pv",
+ "IsLatest": false,
+ "LastModified": "2019-09-18T11:51:23.041Z",
+ "Owner": {
+ "DisplayName": "a9354920-007a-4480-9271-06d3ff7f8426",
+ "ID": "a9354920-007a-4480-9271-06d3ff7f8426"
+ }
+ }
+ ]
+}
+{{< /output >}}
+
+ Each version of the `test.txt` object is represented in the output.
+
+1. To download a previous version of an object, use the `get-object` command and supply the `version-id` of the earliest copy of the object:
+
+ aws s3api get-object --endpoint=http://us-east-1.linodeobjects.com --bucket=bucket-versioning-example --key=test.txt --version-id=4ACJQUNQ1ORV2oZ1SRE7l2M7nTjD1pv test_old.txt
+
+ Be sure to include an output filename for the downloaded object as the last parameter. In the above command the output file is named `test_old.txt`.
+
+ You should see output like the following:
+
+ {{< output >}}
+{
+ "AcceptRanges": "bytes",
+ "LastModified": "Wed, 18 Sep 2019 11:51:23 GMT",
+ "ContentLength": 6,
+ "ETag": "\"9a7b64c98b066602b21f869ae7cd673a\"",
+ "VersionId": "4ACJQUNQ1ORV2oZ1SRE7l2M7nTjD1pv",
+ "ContentType": "binary/octet-stream",
+ "Metadata": {
+ "version-id": "r71GBm28-B2ynT89nAdAEIpXXZwUtqr"
+ }
+}
+{{< /output >}}
+
+ Open the downloaded file and confirm that the first version of the file was downloaded properly.
+
+1. To restore to a previous version of an object using the AWS CLI, you can download the version you want to restore to and then re-upload that file. Alternatively, if there is only one newer version of the object, you can delete the newer version of the object and Object Storage will automatically serve the next most recent version.
diff --git a/docs/platform/object-storage/how-to-use-object-storage/confirm-bucket-delete.png b/docs/platform/object-storage/how-to-use-object-storage/confirm-bucket-delete.png
new file mode 100644
index 00000000000..373ca3a7463
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/confirm-bucket-delete.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/delete-bucket.png b/docs/platform/object-storage/how-to-use-object-storage/delete-bucket.png
new file mode 100644
index 00000000000..a15c2f19eaa
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/delete-bucket.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/delete-object.png b/docs/platform/object-storage/how-to-use-object-storage/delete-object.png
new file mode 100644
index 00000000000..e0216388c04
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/delete-object.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/drag-drop-image-bucket.png b/docs/platform/object-storage/how-to-use-object-storage/drag-drop-image-bucket.png
new file mode 100644
index 00000000000..056ff16058d
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/drag-drop-image-bucket.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/index.md b/docs/platform/object-storage/how-to-use-object-storage/index.md
index 95414984bf5..1ad3e11d658 100644
--- a/docs/platform/object-storage/how-to-use-object-storage/index.md
+++ b/docs/platform/object-storage/how-to-use-object-storage/index.md
@@ -62,7 +62,7 @@ Each Object Storage key pair on your Linode account has complete access to all o
### Generate a Key Pair
-1. Log in to the [Linode Cloud Manager](https://cloud.linode.com).
+1. Log into the [Linode Cloud Manager](https://cloud.linode.com).
{{< note >}}
Object Storage is not available in the Linode Classic Manager.
@@ -102,17 +102,17 @@ There are a number of tools that are available to help manage Linode Object Stor
The Cloud Manager provides a web interface for creating buckets. To create a bucket:
-1. If you have not already, log in the [Linode Cloud Manager](https://cloud.linode.com).
+1. If you have not already, log into the [Linode Cloud Manager](https://cloud.linode.com).
1. Click on the **Object Storage** link in the sidebar, and then click on **Add a Bucket**.

-2. The **Create a Bucket** menu will appear.
+1. The **Create a Bucket** menu will appear.

-3. Add a label for your bucket.
+1. Add a label for your bucket.
{{< note >}}
Bucket labels need to be unique within the same cluster, including buckets on other users' Linode accounts. If the label you enter is already in use, you will have to choose a different label. Additionally, bucket labels have the following rules:
@@ -123,9 +123,91 @@ Bucket labels need to be unique within the same cluster, including buckets on ot
• Cannot contain underscores (_), end with a dash (-) or period (.), have consecutive periods (.), or use dashes (-) adjacent to periods (.)
{{< /note >}}
-4. Choose a cluster location for the bucket to reside in.
+1. Choose a cluster location for the bucket to reside in.
-5. Click **Submit**. You are now ready to upload objects to your bucket using one of the other tools outlined in this guide.
+1. Click **Submit**. You are now ready to [upload objects to your bucket](#upload-objects-to-a-bucket).
+
+### Upload Objects to a Bucket
+
+1. If you have not already, log into the [Linode Cloud Manager](https://cloud.linode.com).
+
+1. Click on the **Object Storage** link in the sidebar. You will see a list of all your buckets. Click on the bucket you'd like to begin uploading objects to.
+
+ 
+
+1. You will see your bucket's **Objects Listing Page**. In the example, the *my-example-bucket* does not yet contain any objects. You can use the **Upload Files Pane** to drag and drop a file from your computer to your object storage bucket.
+
+ {{< note >}}
+You can drag and drop multiple files to the **Upload Files Pane** at one time.
+ {{ note >}}
+
+ 
+
+ You can also click on the **Browse Files** button to bring up your computer's file browser and select a file to upload to your bucket.
+
+ 
+
+1. When the upload has completed, your object will be visible on the **Objects Listing Page**.
+
+ 
+
+### View Bucket Objects
+
+1. If you have not already, log into the [Linode Cloud Manager](https://cloud.linode.com).
+
+1. Click on the **Object Storage** link in the sidebar. You will see a list of all your buckets. Click on the bucket whose objects you'd like to view.
+
+ 
+
+1. You will see your bucket's **Objects Listing Page**, which displays all of your bucket's objects.
+
+ 
+
+1. Click on the ellipsis menu corresponding to the object you'd like to view. Then, select **Open**.
+
+ 
+
+1. A browser window will open your object's unique URL and display your object. In the example, the browser displays a `.png` image.
+
+ 
+
+### Delete Objects from a Bucket
+
+1. If you have not already, log into the [Linode Cloud Manager](https://cloud.linode.com).
+
+1. Click on the **Object Storage** link in the sidebar. You will see a list of all your buckets. Click on the bucket whose objects you'd like to delete.
+
+ 
+
+1. You will see your bucket's **Objects Listing Page**, which displays all of your bucket's objects.
+
+ 
+
+1. Click on the ellipsis menu corresponding to the object you'd like to delete. Then, select **Delete**.
+
+ 
+
+1. A dialog box will appear prompting you to confirm if you'd like to delete the object. Click **Delete** to proceed. Once the object has been deleted, it will no longer be visible on the **Objects Listing Page**.
+
+### Delete a Bucket
+
+{{< note >}}
+You can only delete an empty Object Storage bucket. See the [Delete Objects from a Bucket](#delete-objects-from-a-bucket) section for information on deleting a bucket's objects using the Cloud Manager.
+{{ note >}}
+
+1. If you have not already, log into the [Linode Cloud Manager](https://cloud.linode.com).
+
+1. Click on the **Object Storage** link in the sidebar. You will see a list of all your buckets.
+
+1. Click on the ellipsis menu corresponding to the bucket you'd like to delete. Then, select **Delete**.
+
+ 
+
+1. A dialog box will appear prompting you to enter the bucket's name as a way to confirm that you'd like to delete the bucket. Type your bucket's name into the text entry field and click **Delete**.
+
+ 
+
+ Once the bucket has been deleted, it will no longer be visible on the **Buckets Listing Page**.
## Linode CLI
diff --git a/docs/platform/object-storage/how-to-use-object-storage/object-displayed-in-browser.png b/docs/platform/object-storage/how-to-use-object-storage/object-displayed-in-browser.png
new file mode 100644
index 00000000000..664131fae26
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/object-displayed-in-browser.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/open-an-object.png b/docs/platform/object-storage/how-to-use-object-storage/open-an-object.png
new file mode 100644
index 00000000000..7f652c6e8d6
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/open-an-object.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/select-bucket.png b/docs/platform/object-storage/how-to-use-object-storage/select-bucket.png
new file mode 100644
index 00000000000..c00d186895c
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/select-bucket.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/successful-object-upload.png b/docs/platform/object-storage/how-to-use-object-storage/successful-object-upload.png
new file mode 100644
index 00000000000..867c4ce5404
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/successful-object-upload.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/upload-with-file-browser.png b/docs/platform/object-storage/how-to-use-object-storage/upload-with-file-browser.png
new file mode 100644
index 00000000000..3453d9b87f7
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/upload-with-file-browser.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/view-your-objects.png b/docs/platform/object-storage/how-to-use-object-storage/view-your-objects.png
new file mode 100644
index 00000000000..96c476e28e8
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/view-your-objects.png differ
diff --git a/docs/platform/object-storage/how-to-use-object-storage/view-your-uploaded-object.png b/docs/platform/object-storage/how-to-use-object-storage/view-your-uploaded-object.png
new file mode 100644
index 00000000000..c976ea9ed37
Binary files /dev/null and b/docs/platform/object-storage/how-to-use-object-storage/view-your-uploaded-object.png differ
diff --git a/docs/platform/object-storage/lifecycle-policies/index.md b/docs/platform/object-storage/lifecycle-policies/index.md
new file mode 100644
index 00000000000..1e1e5250683
--- /dev/null
+++ b/docs/platform/object-storage/lifecycle-policies/index.md
@@ -0,0 +1,239 @@
+---
+author:
+ name: Linode Community
+ email: docs@linode.com
+description: 'Use lifecycle policies to manage deleting objects in Linode Object Storage.'
+keywords: ['object','storage','lifecycle','policy','policies','delete','bucket','version','multipart']
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+published: 2019-10-18
+modified_by:
+ name: Linode
+title: "Manage Objects with Lifecycle Policies"
+contributor:
+ name: Linode
+---
+
+While deleting a few objects in an Object Storage bucket might not take that long, when the objects number in the thousands or even millions the time required to complete the delete operations can easily become unmanageable. When deleting a substantial amount of objects, it's best to use *lifecycle policies*. These policies can be represented in XML; here's an (incomplete) snippet of an action that will delete objects after 1 day:
+
+{{< file >}}
+
+ 1
+
+{{< /file >}}
+
+A lifecycle policy is applied to a bucket. Policies are sets of rules that govern the management of objects after they have aged for a certain amount of time. For instance, you can create a lifecycle policy that deletes objects every thirty days, or once a week. This is useful for cases where the data in a bucket becomes outdated, such as when collecting activity logs.
+
+## In This Guide
+
+This guide will first describe [when policies are enforced](#when-policies-are-enforced) and will then explain how to create and delete lifecycle policies with two tools:
+
+- [s3cmd command line interface](#s3cmd) (CLI): In addition to deleting objects, more complicated policies can be managed with s3cmd, including deleting old versions of objects that have been retained, and failed multipart uploads.
+
+- [Cyberduck desktop application](#cyberduck) (GUI): Cyberduck does not feature as many policy options, but they can be managed through a point-and-click interface.
+
+## Before You Begin
+
+* Familiarize yourself with Linode Object Storage by reading the [How to Use Object Storage](/docs/platform/object-storage/how-to-use-object-storage/) guide.
+* For demonstration purposes, you can create an Object Storage bucket with a few objects that you will later delete.
+
+## When Policies are Enforced
+
+Lifecycle policies are triggered starting at midnight of the Object Storage cluster's local time. This means that if you set a lifecycle policy of **one day**, the objects will be deleted **the midnight after they become 24 hours old**.
+
+For example, if an object is created at 5PM on January 1, it will reach 24 hours in age at 5PM on January 2. The policy will then be enforced on the object at 12AM on January 3.
+
+{{< note >}}
+There is a chance that a lifecycle policy will not delete all of the files in a bucket the first time the lifecycle policy is triggered. This is especially true for buckets with upwards of a million objects. In cases like these, *most* of the objects are deleted, and any remaining objects are typically deleted during the next iteration of the lifecycle policy's rules.
+{{ note >}}
+
+## Create and Delete Lifecycle Policies
+
+### s3cmd
+
+[s3cmd](https://s3tools.org/s3cmd) allows users to set and manage lifecycle policies from the command line. In this section, you will find instructions on how to create and manage lifecycle policies to delete objects, previous versions of objects, and failed multipart uploads using s3cmd.
+
+{{< note >}}
+If you don't have s3cmd set up on your computer, visit the [Install and Configure s3cmd](/docs/platform/object-storage/how-to-use-object-storage/#install-and-configure-s3cmd) section of the How to Use Linode Object Storage guide.
+{{< /note >}}
+
+#### Creating a Lifecycle Policy File
+
+In S3-compatible Object Storage, a lifecycle policy is represented by an XML file. You can use your preferred text editor to create this XML file. Consider the following lifecycle policy file:
+
+{{< file "lifecycle_policy.xml" xml >}}
+
+
+ delete-all-objects
+
+ Enabled
+
+ 1
+
+
+
+{{< /file >}}
+
+The above lifecycle policy deletes all objects in the bucket after one day. Each lifecycle policy file needs a `LifecycleConfiguration` block and a nested `Rule` block. The `Rule` block must contain `Prefix` and `Status`, and at least one action, like the `Expiration` block. It's also a good idea to include an `ID` block:
+
+| Block | Description |
+|-------|-------------|
+| `ID` | Defines a name for the lifecycle policy rule. If your lifecycle policy contains multiple rules, then the ID for each should be unique. If one is not specified in your policy file, then a random alphanumeric ID will be assigned to your policy when the policy is applied to a bucket. |
+| `Prefix` | This string is used to select objects for deletion with the same matching prefix. For example, objects that begin with `error_report-` could be targeted for deletion by providing this prefix. This Prefix can be empty if you want a rule to apply to all files in a bucket. |
+| `Status` | A string value describing the status of the lifecycle policy. To enable the policy, set this value to `Enabled`. To disable the policy set the value to `Disabled`. |
+| `Expiration` | Contains the `Days` block. The `Days` block is the number of days before this rule will be enforced. In the above example, the `Days` is set to `1`, meaning that the objects in the bucket will be deleted after one day. |
+
+#### Additional Actions
+
+Other actions can also be specified in a rule:
+
+- `NoncurrentVersionExpiration` block, and its child, `NoncurrentDays`. These are used to control the lifecycle of objects with multiple older versions, and should only be used with buckets that have [bucket versioning](/docs/platform/object-storage/bucket-versioning/) enabled. Using this option will delete objects that are not the newest, most current version. Below is an example of how to use `NoncurrentVersionExpiration`:
+
+ {{< file "lifecycle_policy_noncurrent_versions.xml" xml >}}
+
+
+ delete-prior-versions
+
+ Enabled
+
+ 1
+
+
+
+{{ file >}}
+
+- `AbortIncompleteMultipartUpload`, and its child, `DaysAfterInitiation`. These work similarly to `NoncurrentVersionExpiration`, but instead of deleting previous versions of objects, they will delete failed multipart uploads. The following will delete failed multipart uploads three days after they were initiated:
+
+ {{< file "lifecycle_policy_multipart_upload.xml" xml >}}
+
+
+ delete-prior-versions
+
+ Enabled
+
+ 3
+
+
+
+{{ file >}}
+
+ {{< disclosure-note "About multipart uploads" >}}
+Objects that are part of failed multipart uploads (the mechanism by which large files are uploaded) stay within Object Storage buckets, counting towards your total Object Storage costs. s3cmd will automatically initiate a multipart upload when a file is larger than 15MB. Lifecycle policies are a great way to clear out stale multipart uploads.
+{{< /disclosure-note >}}
+
+#### Multiple Actions in One Rule
+
+More than one action can be specified in a single rule. For example, you may want to both expire the current version of an object after a set number of days and also remove old versions of it after another period of time. The following policy will delete the current version of an object after 10 days and remove any noncurrent versions of an object 3 days after they are demoted from the current version:
+
+{{< file "lifecycle_policy_multipart_upload.xml" xml >}}
+
+
+ delete-prior-versions
+
+ Enabled
+
+ 10
+
+
+ 3
+
+
+
+{{ file >}}
+
+{{< note >}}
+As a reminder, if a versioned object is deleted, only the current version of the object will be deleted and all older versions will be preserved in the bucket. For this reason, the above rule has the effect of deleting any objects if they are not updated within 10 days, and then removing the remaining object versions after 3 days.
+{{< /note >}}
+
+#### Multiple Rules
+
+A lifecycle policy file can only contain one `LifecycleConfiguration` block, but the `LifecycleConfiguration` block can contain more than one `Rule`. For instance, if you had a bucket that contained both error and general output logs, you could set a lifecycle policy that saves error logs for a week but deletes standard logs at the end of every day:
+
+{{< file "lifecycle_policy_error_and_standard_logs.xml" xml >}}
+
+
+ delete-error-logs
+ error
+ Enabled
+
+ 7
+
+
+
+ delete-standard-logs
+ logs
+ Enabled
+
+ 1
+
+
+
+{{ file >}}
+
+#### Uploading the Lifecycle Policy to a Bucket
+
+In order to apply a lifecycle policy to a bucket with s3cmd, you need to upload the lifecycle file to the bucket. This operation is not a normal PUT operation. Instead, the command to use is `setlifecycle`, followed by the name of the lifecycle policy file, and the name of bucket:
+
+ s3cmd setlifecycle lifecycle_policy.xml s3://lifecycle-policy-example
+
+You should see output like the following:
+
+ s3://lifecycle-policy-example/: Lifecycle Policy updated
+
+
+Once the lifecycle policy has been uploaded, objects will be deleted according to the policy set in place.
+
+#### Viewing a Bucket's Lifecycle Policy
+
+To view a lifecycle policy after it has been uploaded to a bucket, use the `getlifecycle` command and provide the bucket name:
+
+ s3cmd getlifecycle s3://lifecycle-policy-example
+
+You should see the contents of the XML file that was uploaded:
+
+
+
+
+ delete-all
+
+ Enabled
+
+ 1
+
+
+
+
+#### Deleting a Lifecycle Policy
+
+To delete a lifecycle policy that you've uploaded, effectively disabling it, use the `dellifecycle` command and provide the bucket name:
+
+ s3cmd dellifecycle s3://lifecycle-policy-example
+
+You'll see a confirmation that the lifecycle policy was deleted:
+
+ s3://lifecycle-example/: Lifecycle Policy deleted
+
+### Cyberduck
+
+[Cyberduck](https://cyberduck.io/) allows less control over lifecycle polices than the s3cmd CLI. In particular, Cyberduck does not allow you to set a lifecycle policy that removes outdated versions of objects stored in buckets where [versioning](/docs/platform/object-storage/bucket-versioning/) is enabled, nor does it allow you to delete multipart uploads. Cyberduck also limits the length of a lifecycle policy to commonly used time spans. Below you will learn how to set a lifecycle policy using Cyberduck.
+
+{{< note >}}
+If you don't have Cyberduck set up on your computer, visit the [Install and Configure Cyberduck](/docs/platform/object-storage/how-to-use-object-storage/#install-and-configure-cyberduck) section of the How to Use Linode Object Storage guide.
+{{< /note >}}
+
+#### Enable a Lifecycle Policy
+
+1. **Right click** or **control +** click on the bucket for which you would like to set a lifecycle policy. This will bring up the bucket info menu.
+
+1. Click on the **S3** tab to open the S3 bucket settings.
+
+ [](lifecycle-policies-cyberduck-settings.png)
+
+1. Click on the checkbox labeled **Delete files** and select a time interval from the drop-down menu below it.
+
+ [](lifecycle-policies-cyberduck-lifecycle-settings.png)
+
+This will enable the lifecycle policy and the objects within the bucket will be deleted after the designated time.
+
+#### Disable a Lifecycle Policy
+
+To disable a lifecycle policy, uncheck the box entitled **Delete Files** that you checked in the previous section.
\ No newline at end of file
diff --git a/docs/platform/object-storage/lifecycle-policies/lifecycle-policies-cyberduck-lifecycle-settings.png b/docs/platform/object-storage/lifecycle-policies/lifecycle-policies-cyberduck-lifecycle-settings.png
new file mode 100644
index 00000000000..cc068b1c18c
Binary files /dev/null and b/docs/platform/object-storage/lifecycle-policies/lifecycle-policies-cyberduck-lifecycle-settings.png differ
diff --git a/docs/platform/object-storage/lifecycle-policies/lifecycle-policies-cyberduck-settings.png b/docs/platform/object-storage/lifecycle-policies/lifecycle-policies-cyberduck-settings.png
new file mode 100644
index 00000000000..785c002d07f
Binary files /dev/null and b/docs/platform/object-storage/lifecycle-policies/lifecycle-policies-cyberduck-settings.png differ
diff --git a/docs/platform/object-storage/pricing-and-limitations/index.md b/docs/platform/object-storage/pricing-and-limitations/index.md
new file mode 100644
index 00000000000..1dfe00e0b25
--- /dev/null
+++ b/docs/platform/object-storage/pricing-and-limitations/index.md
@@ -0,0 +1,40 @@
+---
+author:
+ name: Linode Community
+ email: docs@linode.com
+description: 'Object Storage pricing breakdown, storage limits, transfer quotas, and other pertinent information.'
+keywords: ['object','storage','pricing','price','limit','transfer']
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+published: 2019-10-07
+modified_by:
+ name: Linode
+title: "Object Storage Pricing and Limitations"
+contributor:
+ name: Linode
+---
+
+{{< note >}}
+Object Storage is currently in a closed early access Beta, and you may not have access to Object Storage through the Cloud Manager or other tools. To gain access to the Early Access Program (EAP), open up a Customer Support ticket noting that you'd like to be included in the program, or e-mail objbeta@linode.com -- beta access is completely free. This guide reflects the policies that will be enacted when Object Storage is made available to the general public.
+{{ note >}}
+
+Linode Object Storage offers affordable and full-featured cloud storage for unstructured data and static sites. This guide will outline Object Storage pricing, storage limitations, and data transfer quotas.
+
+## Pricing
+
+Linode Object Storage has a minimum monthly cost of $5, which provides 250 gigabytes of storage. Each additional gigabyte of storage will cost $0.02.
+
+## Storage Limitations
+
+Currently, Object Storage accounts are limited 10 terabytes of storage, or 100,000 objects, whichever comes first. Accounts can have up to 10 buckets.
+
+{{< note >}}
+If you need to increase the storage limit, the object limit, or the bucket limit, please [open up a Customer Support ticket](https://www.linode.com/docs/platform/billing-and-support/support/#contacting-linode-support).
+{{ note >}}
+
+## Transfer Quotas
+
+Object Storage adds 1 terabyte of outbound data transfer to your data transfer pool. At this time, all outbound data, including data transfer to a Linode in the same data center, is billable. You are not charged for uploading objects (inbound traffic) to Object Storage. Any further outbound data is charged at a rate of $0.02 a gigabyte. For more information on network transfer pools, review our [Network Transfer Quota guide](https://linode.com/docs/platform/billing-and-support/network-transfer-quota/).
+
+{{< note >}}
+The 1 terabyte of transfer from Object Storage is not prorated. If you use Object Storage at any point during the month, 1 terabyte of transfer will be added to your pool.
+{{< /note >}}
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/index.md b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/index.md
new file mode 100644
index 00000000000..83a63cc377e
--- /dev/null
+++ b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/index.md
@@ -0,0 +1,39 @@
+---
+author:
+ name: Nick Brewer
+ email: docs@linode.com
+description: 'Select and deploy the Linux distribution of your choice.'
+keywords: ["linux", "linode manager", "image"]
+license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
+modified: 2017-05-08
+modified_by:
+ name: Linode
+published: 2017-05-08
+title: Deploy an Image to a Linode
+hiddenguide: true
+cloud_manager_link: quick-answers/linode-platform/deploy-an-image-to-a-linode/
+---
+
+This QuickAnswer will show you how to deploy a Linux distribution to your Linode. See our [Getting Started](/docs/getting-started-classic-manager/) and [Disks and Configuration Profiles](/docs/platform/disk-images/disk-images-and-configuration-profiles-classic-manager/) guides for additional information.
+
+1. Once you've created your Linode, select it from the **Linodes** tab to access the Dashboard. Click on **Deploy an Image**:
+
+ [](linode-manager-dashboard-newacct.png)
+
+ The *Deploy* page will open:
+
+ [](linode-manager-deploy-an-image.png)
+
+2. Select a Linux distribution from the **Image** menu.
+
+3. Enter a size for the disk in the **Deployment Disk Size** field. By default, all of the available space on your Linode is allocated. Note that the minimum deployment size for you distribution is listed under the disk size field - in this example the minimum is **900MB** for a Debian 8 image.
+
+4. Select a swap disk size from the **Swap Disk** menu. Unless you have a specific reason to use more, the default **256MB** is recommended.
+
+5. Enter a root password for your Linode in the **Root Password** field. This password must be provided when you log in to your Linode via SSH; it must be at least 6 characters long and contain at least two of the following:
+
+ - lowercase and uppercase case letters
+ - numbers
+ - punctuation marks
+
+6. Click **Deploy**. You can monitor the progress of your distribution deployment from the Linode's job queue. Once it completes, click the **Boot** button to boot your Linode.
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-dashboard-newacct.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-dashboard-newacct.png
similarity index 100%
rename from docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-dashboard-newacct.png
rename to docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-dashboard-newacct.png
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-dashboard-newacct_small.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-dashboard-newacct_small.png
similarity index 100%
rename from docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-dashboard-newacct_small.png
rename to docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-dashboard-newacct_small.png
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-deploy-an-image.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-deploy-an-image.png
similarity index 100%
rename from docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-deploy-an-image.png
rename to docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-deploy-an-image.png
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-deploy-an-image_small.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-deploy-an-image_small.png
similarity index 100%
rename from docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/linode-manager-deploy-an-image_small.png
rename to docs/quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/linode-manager-deploy-an-image_small.png
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/add-a-configuration-link.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/add-a-configuration-link.png
new file mode 100644
index 00000000000..bafa65cce98
Binary files /dev/null and b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/add-a-configuration-link.png differ
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/add-a-disk-link.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/add-a-disk-link.png
new file mode 100644
index 00000000000..015775ca34a
Binary files /dev/null and b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/add-a-disk-link.png differ
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/boot-this-config-option.png b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/boot-this-config-option.png
new file mode 100644
index 00000000000..c2aa98281db
Binary files /dev/null and b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/boot-this-config-option.png differ
diff --git a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/index.md b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/index.md
index 465ee53b3f2..15e33d7cda2 100644
--- a/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/index.md
+++ b/docs/quick-answers/linode-platform/deploy-an-image-to-a-linode/index.md
@@ -1,37 +1,82 @@
---
author:
- name: Nick Brewer
+ name: Linode
email: docs@linode.com
description: 'Select and deploy the Linux distribution of your choice.'
-keywords: ["linux", "linode manager", "image"]
+keywords: ["linux", "linode manager", "image", "cloud manager"]
license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
-modified: 2017-05-08
modified_by:
name: Linode
-published: 2017-05-08
+published: 2019-10-11
title: Deploy an Image to a Linode
+classic_manager_link: quick-answers/linode-platform/deploy-an-image-to-a-linode-classic-manager/
---
-This QuickAnswer will show you how to deploy a Linux distribution to your Linode. See our [Getting Started](/docs/getting-started) and [Disks and Configuration Profiles](/docs/platform/disk-images/disk-images-and-configuration-profiles) guides for additional information.
+When you first create a Linode, you generally [deploy a Linux distribution or other image](/docs/getting-started/#create-a-linode) to it upon creation. However, it is also possible to deploy additional images and Linux distributions to your Linode that will exist alongside your first image. Additionally, you can switch between these extra images by rebooting your Linode. This QuickAnswer guide will show you how to deploy an additional image.
+
+{{< note >}}
+To deploy additional images, your Linode will need some unallocated space for those new images. When following the steps below, if you find that you don't have sufficient unallocated space, then you have two options:
+
+- [Resize/shrink other disks](/docs/quick-answers/linode-platform/resize-a-linode-disk/) on your Linode to make some room.
+- [Upgrade your Linode](/docs/platform/disk-images/resizing-a-linode/) to a plan that offers more disk space.
+{{< /note >}}
+
+## Deploy an Image
+
+1. Log into the [Linode Cloud Manager](https://cloud.linode.com/). Click on the **Linodes** link in the sidebar navigation. A table of your Linodes will appear.
+
+1. Click on the row corresponding to your Linode. A dashboard for your Linode will appear.
+
+1. Click on the **Advanced** tab from this page, and find the **Disks** panel that appears below it.
+
+ [](add-a-disk-link.png)
+
+1. On this panel, click the **Add a Disk** link.
+
+1. The **Add Disk** form will appear. Select the **Create from Image** option at the top of the form, then complete the remaining fields in the form:
+
+ | Field | Description |
+ |-------|-------------|
+ | Label | A name for the disk created from the image that you will select. |
+ | Image | The Linux distribution or other image that you would like to use. If you have any [custom images](/docs/platform/disk-images/linode-images/) saved, they will be listed at the bottom of the dropdown menu. |
+ | Root Password | A strong, complex, and unique password for the root user on your new image's disk. |
+ | SSH Keys | Any [SSH keys](/docs/security/authentication/use-public-key-authentication-with-ssh/) that you would like to assign to the root user on your new image's disk. |
+ | Size | The size of the disk that will be deployed. If you also want to create a new swap disk, make sure to enter a value that's less than the **Maximum Size** label below this field. The current amount of unallocated space on your Linode will be listed in this label. |
+
+1. When you have completed the form, click the **Add** button.
+
+### Optional: Deploy a Swap Disk
+
+Your new Linux distribution or image will often require a swap disk in order to boot. If you already have a swap disk on your Linode from a previous image deployment (visible under the **Disks** panel), you can reuse that same disk with your new image. Otherwise, you can create a new swap disk:
+
+1. Revisit the **Disks** panel under the **Advanced** tab for your Linode. Click the **Add a Disk** link.
+
+1. In the **Add Disk** form that appears, choose the **swap** option from the **Filesystem** dropdown menu. Then enter a label and size (usually 128MB, 256MB, or 512MB). Click the **Add** button to complete the form.
+
+## Create a Configuration Profile
-1. Once you've created your Linode, select it from the **Linodes** tab to access the Dashboard. Click on **Deploy an Image**:
+To boot your Linode with the new image, you'll need a [configuration profile](/docs/platform/disk-images/disk-images-and-configuration-profiles/#configuration-profiles) that is associated with the image:
- [](linode-manager-dashboard-newacct.png)
+1. Navigate to the **Advanced** tab for your Linode and find the **Configuration** panel underneath it. Click the **Add a Configuration** link on this panel:
- The *Deploy* page will open:
+ [](add-a-configuration-link.png)
- [](linode-manager-deploy-an-image.png)
+1. The **Add Linode Configuration** form will appear. Enter values for these fields:
-2. Select a Linux distribution from the **Image** menu.
+ | Field | Value |
+ |-------|-------------|
+ | Label | A name for the configuration profile. |
+ | Comments | Enter any comments that may help you remember the purpose for your new configuration profile, or any other notes you'd like to record. |
+ | Select a Kernel | Select the **GRUB 2** option. |
+ | /dev/sda | Choose the disk for the new image/Linux distribution that you deployed. |
+ | /dev/sdb | Choose your swap disk. |
-3. Enter a size for the disk in the **Deployment Disk Size** field. By default, all of the available space on your Linode is allocated. Note that the minimum deployment size for you distribution is listed under the disk size field - in this example the minimum is **900MB** for a Debian 8 image.
+ For all of Linode's standard distribution images, the other fields can retain their default values. For custom images, you may need to update other parts of the configuration profile; review the [Disks and Configuration Profiles](/docs/platform/disk-images/disk-images-and-configuration-profiles/#configuration-profiles) and [Install a Custom Distribution on a Linode](/docs/tools-reference/custom-kernels-distros/install-a-custom-distribution-on-a-linode/) articles for further guidance.
-4. Select a swap disk size from the **Swap Disk** menu. Unless you have a specific reason to use more, the default **256MB** is recommended.
+## Next Steps
-5. Enter a root password for your Linode in the **Root Password** field. This password must be provided when you log in to your Linode via SSH; it must be at least 6 characters long and contain at least two of the following:
+To reboot with the new image, navigate to the **Configuration** panel under the **Advanced** tab for your Linode. Select the **more options ellipsis** for your new profile and click the **Boot This Config** option in the dropdown menu that appears:
- - lowercase and uppercase case letters
- - numbers
- - punctuation marks
+[](boot-this-config-option.png)
-6. Click **Deploy**. You can monitor the progress of your distribution deployment from the Linode's job queue. Once it completes, click the **Boot** button to boot your Linode.
+For help with configuring the software on your new image, review the [Getting Started](/docs/getting-started/) and [How to Secure Your Server](/docs/security/securing-your-server/) guides.
diff --git a/docs/quick-answers/linux/how-to-use-fsck-qa/index.md b/docs/quick-answers/linux/how-to-use-fsck-qa/index.md
index a34b1ed5fbc..697f18fc066 100644
--- a/docs/quick-answers/linux/how-to-use-fsck-qa/index.md
+++ b/docs/quick-answers/linux/how-to-use-fsck-qa/index.md
@@ -24,14 +24,37 @@ On some systems, fsck runs automatically after an unclean shutdown or after a ce
## When to Use fsck
Use fsck to check your file system if your system fails to boot, if files on a specific disk become corrupt, or if an attached drive does not act as expected.
-Unmount the disks you intend to work on before attempting to check or repair them.
-{{< caution >}}
-Unmount the target disk first. You risk corrupting your file system and losing data if you run fsck on an active disk.
-{{< /caution >}}
+{{< note >}}
+To run this utility you will want to boot into rescue mode. Please see our [Troubleshooting Guide: Booting into Rescue Mode](https://www.linode.com/docs/troubleshooting/rescue-and-rebuild/#booting-into-rescue-mode) for guidance.
+{{ note >}}
+
+### Verify Disks are Unmounted
+
+1. Verify that the disks you wish to check are unmounted. You risk corrupting your file system and losing data if you run fsck on an active disk. To do this, enter the following command:
+
+ df -h
+
+1. You will see a similar output:
+
+ {{< output >}}
+root@ttyS0:~# df -h
+Filesystem Size Used Avail Use% Mounted on
+tmpfs 739M 1016K 738M 1% /media/ramdisk
+/dev/sdh 160M 160M 0 100% /media/sdh
+/dev/loop0 146M 146M 0 100% /media/compressed_root
+unionfs 739M 1016K 738M 1% /
+devtmpfs 10M 0 10M 0% /dev
+{{< /output >}}
+
+ Your primary disks should not appear in the list. As long as your device does not appear in the example output from the `df -h` command, you can run a filesystem check on it.
## How to Check for Errors on a Disk
+{{< caution >}}
+Never run fsck on a mounted disk. Do not continue unless you’re sure that the target disk is unmounted. You risk corrupting your file system and losing data if you run fsck on an active disk.
+{{ caution >}}
+
Run fsck on the target disk, using the desired options. This example checks all file systems (`-A`) on `/dev/sdb`:
fsck -A /dev/sdb
@@ -75,6 +98,6 @@ To check and attempt to repair any errors on `/dev/sdb`, use this format:
fsck -y /dev/sdb
-## What if fsck got interrupted?
+## What if fsck Gets Interrupted?
If fsck gets interrupted, it will complete any checks in process, but will not attempt to repair any errors it finds.