# Invite & The Basics

Welcome! Let's get you started.

### Useful links

{% hint style="success" %}

## [➕ Invite DeGore](https://discord.com/oauth2/authorize?client_id=862039253574746125\&scope=bot\&permissions=3959811190\&redirect_uri=https%3A%2F%2Funitedweco.de%2Fdegore%2F\&scope=bot%20applications.commands)

{% endhint %}

{% hint style="info" %}

## [🤝 Support Server](https://discord.com/invite/hjBjMKxxte)

{% endhint %}

{% hint style="info" %}

## [⭐ Upgrade to DeGore Plus](https://unitedweco.de/degore/plus)

{% endhint %}


# Get Started // Onboarding

Get Started with DeGore Here!

{% embed url="<https://youtu.be/4y470jnDkdo>" %}


# Overview


# What is DeGore?

A quick introduction to DeGore, the leading image moderation bot for Discord communities.

<figure><img src="https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2Fz23ulVEVAayGMvNQf1Xb%2FDeGore_Thumbnail_Compressed.png?alt=media&amp;token=2ba0549b-3851-4dfb-8dc1-7db77f020a3f" alt=""><figcaption></figcaption></figure>

## Image moderation, automated.

Using AI magic, DeGore scans images, GIFs, embeds, image links and thumbnails sent in your discord server and instantly deletes images containing gore, explicit, drug and suggestive imagery in under a second.

**Just add the bot to your server, run `/setup` and you're all set!**


# About DeGore

A short history of how DeGore came to be the leading image moderation bot for Discord Servers.

## A Short Backstory

When I first started coding DeGore, I had set out with a goal: to create the best and most feature-rich image moderation Discord bot. This whole idea came to mind after I unwillingly stumbled upon a not-so-pleasant animated gore GIF which a member had sent in a community Discord server. Needless to say, ***it was disgusting***, to say the least. A while later, the image was deleted by a moderator.

That's when I thought to myself: "What if I could automate this? Why isn't this already a thing on Discord?". After spending a while trying to find an auto-moderation image bot to no avail, I decided it was time to create my own.

Now, since there weren't any already-existing solutions for image moderation, there wasn't exactly anywhere I could take ideas and inspiration from. This was arguably the most challenging part - coming up with the whole structure of an AI image moderation bot from scratch was pretty tricky and had some obstacles that needed to be overcome.

With the little experience I had in discord.js at the time, on the 11th of March, the initial project files were created and I got to programming. After hours of AI R\&D and going through a lot of library and API documentation, I finally had the first version of DeGore up and running within the first few days. That's when I made my first commit to DeGore's private GitHub repository:

![DeGore's first ever commit on GitHub](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2FJqm2WZeIxKl6c81MwcM3%2Fimage.png?alt=media\&token=7c2be89f-b079-41da-b965-ff8d30e5c1be)

...and that's when DeGore first came to life - on the 19th of March, 2021.

![DeGore's first messages](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2FWhmVOZC3U0eBF1dgA29k%2Fimage.png?alt=media\&token=1acc4150-f4bb-43a5-88cd-a88736acc2ad)

When I first managed to get DeGore to detect NSFW imagery, I was over the moon, quite literally jumping in excitement. AI is incredibly fun to tinker with, and this was my first proper application of Artificial Intelligence. I could feel it - this was the start to something great.

## DeGore, Today <a href="#degore-today" id="degore-today"></a>

It's mind-boggling to look back and see how far DeGore has come. Nowadays, DeGore is protecting 800,000+ users in over 1,000 communities. DeGore is growing like a champion.

I couldn't be happier with the amazing community we've created in our official Discord server ([DeGore's Lobby](https://discord.gg/NnsFt6xKsc)), and feel incredibly proud that DeGore is playing a role in helping to keep users just a little bit safer in their communities, as well as giving community moderators and administrators ease of mind.

There are so many exciting upcoming new features, including DeGore's Web Dashboard and an innovative approach to centralized moderation.\
Here's a sneak peek of something that's coming this summer 👀:

![Coming soon to your local DeGore this summer ;)](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2FCl8LnS1UoeEQe09Zgn1p%2Fimage.png?alt=media\&token=af9dab72-2165-42dc-8e8b-f36350d7b582)

## Read the full story [on our blog](https://blog.unitedweco.de/celebrating-a-year-of-degore/).


# About DeGore Plus

Upgrade your community's protection.

<figure><img src="https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2FCp5E5vdrwmxCFrjxxNCQ%2FDeGore%20Plus%20Logo.png?alt=media&amp;token=5e2e692a-ab13-42ea-ab5c-e6b58e7ee708" alt=""><figcaption><p>DeGore Plus 😳</p></figcaption></figure>

DeGore Plus is a monthly subscription which upgrades your DeGore experience by providing you with as many image scans as you choose every month (depending on the Tier you choose), allowing DeGore to continue protecting your community.\
**You'll also get all the following features:**

<figure><img src="https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2FRlYv2fKTEewBqnOEAUVe%2Fimage.png?alt=media&amp;token=8b5d7d85-a72a-421e-a36e-7681405d7bfa" alt=""><figcaption><p><em>"now that's a ton of useful features if I say so myself!"</em><br><em>-someone, probably</em></p></figcaption></figure>

### Sounds good? Let's go!

{% hint style="success" %}

## [Get DeGore Plus](https://unitedweco.de/degore/plus)

{% endhint %}

### *Doitdoitdoitdoitdoitdoitdoit*


# Setup Command

Get DeGore Set-up in one easy step using the /setup slash command.

## `/setup`

**This is an important command to get started with a tailored configuration to fit your server's needs.** With just this one command, you can configure a logging channel, whitelisted staff roles, custom actions, and ensure that DeGore has the adequate permissions to protect your community. **Administrators** and the **Server Owner** are the only members that can run this command.


# Configuration Commands

Learn more about configuring DeGore exactly to your community's needs.

## `/config logging`

**Easily set a logging channel for DeGore to send important alerts to.** For instance, you'll receive alerts whenever an image is deleted, an auto-timeout/kick/ban takes place or for detection categories in which you set the action to just alert the moderators. Users with the **Administrator** permission are the only members that can run this command.

## `/config images`

**Configure the categories of images DeGore will moderate**, and the actions that should be taken for each category. Users with the **Administrator** permission are the only members that can run this command.

## `/config staff`

**Quickly view, add or remove up to 5 roles at a time from the staff whitelist.** Users with the **Administrator** permission are the only members that can run this command.


# Blacklist & Whitelist Commands

Learn more about DeGore's blacklisting and whitelisting commands here.

## `/blacklist`

**Quickly view, add or remove images that are in the blacklist.** Images in the blacklist will be immediately deleted by DeGore no matter what. It is recommended to use the blacklist if you want to prevent a specific image from being sent. Users with the **Manage Messages** permission are the only members that can run this command.

## `/whitelist`

**Quickly view, add or remove images that are in the whitelist.** Images in the whitelist will be completely ignored by DeGore and will not be deleted no matter what. It is recommended to use the whitelist if DeGore accidentally deletes a safe image. Users with the **Manage Messages** permission are the only members that can run this command.


# Server Statistics Command

Instantly get statistics regarding DeGore and your server.

## `/stats`

View the image scans you have remaining, your current subscription tier (if any), the images scanned and deleted, as well as the advanced statistics for insights on the most commonly deleted image categories. Users with the **Manage Messages** permission are the only members that can run this command.


# User Privacy Command

Privacy is a fundamental human right. Here at DeGore, it's also one of our core values. DeGore processes thousands of images every day, so ensuring our users' privacy is our #1 priority.

## `/privacy`

**Get a link to our website to read our Privacy Policy.**


# Help Command

Stuck or need help? This is the right command for you. Don't forget to reach out to our support team if you still need help!

## `/help`

**Get a list of all of DeGore's commands**, with an intuitive selection system.


# FAQ

Answers to Frequently Asked Questions about DeGore can be found here.

### 🌐 Where can I visit DeGore's site?

You can visit DeGore's official site at: <https://unitedweco.de/degore>

### ⚠️ DeGore has sent an alert saying 'Out of Image Scans!'

**If you are on the free tier, this indicates that you have run out of images to be scanned.**\
**To resume protection as soon as possible, you should visit** [**DeGore's webpage**](https://unitedweco.de/degore/plus) **to purchase DeGore Plus.** DeGore plus is a monthly subscription which will get you extra image scans for your server based on the plan you choose. Simply choose a plan that's right for your server's size and you're all set. We have made sure to offer a variety of different plans to cover servers of all sizes, with value in mind.\
**Not sure which plan to choose?** We suggest estimating your monthly usage by **looking at your server's size** and **based on how active it is.** You're always welcome to contact our speedy support team at any time if you need help deciding! We're always here for you.\
\--\
If you already are a DeGore Plus subscriber, this means that you have run out of your monthly subscription's allocated image scans. Simply [get in touch with our support team](https://discord.gg/aPnkkWF75Y) and we'll help you get things sorted in a jiffy.

### 🔗 What extensions does DeGore Support?

DeGore currently supports the following extensions:

* [x] .PNG
* [x] .JPG
  * [x] .JPEG
  * [x] .JFIF
* [x] .TIF
  * [x] .TIFF
* [x] .WEBP
* [x] .GIF

### 💳 I've purchased DeGore Plus but it has yet to activate on my server!

If after 5 minutes of purchase your subscription is not activated correctly, please create a ticket and we'll get your subscription sorted in no time!

### 🤝 Where can I join DeGore's Support Server?

You can join by [clicking this link](https://discord.gg/hjBjMKxxte).


# 24/7 Bot Hosting (Free Credit!)

Here's a tutorial on how to get started with hosting your bot on Linode for free by claiming $100 in credit for free, and enjoy enterprise-grade hosting for bots of all sizes!

## Introduction

### Linode's powerful datacenters have been hosting DeGore's core infrastructure with an impressive 99.99% uptime, and we can confirm that Linode is amongst the best choices for cloud server hosting, to power your discord bot of any size.

Have you been looking for an intuitive and reliable host for your Discord bot? Then you've come to the right place. Read along and we'll get your bot hosted 24/7 on Linode's servers for no initial cost.\
This tutorial will focus on how to host your NodeJS bot, however it can be easily adapted for all other languages.

## Why Linode?

**Linode offers impeccable value when it comes to virtual private servers.** For just $5 a month, you can utilize their high performance cloud computing infrastructure with free bundled support, transfer, DDoS Protection and much more for the most affordable prices.\
The best part is that once your product or service becomes super popular and you may need to upgrade your server, **with Linode you can upgrade your system's hardware and scale with just a few clicks.**\
**The servers also come bundled with many great useful features**, such as automatic backups, automatic server re-starts in the case of a crash and even more.\
**I've been using Linode and my experience with them so far has been excellent.** Their support team is also notably incredibly fast and helpful, ready to support you 24/7.

## Step 1: Create an account on Linode

Let's get started! To begin, visit Linode's site at [https://linode.com/](https://www.linode.com/lp/free-credit-short/?utm_source=google\&utm_medium=cpc\&utm_campaign=11178784489_109179215203\&utm_term=g_kwd-4269612793_p_linode) and click on **Sign Up**.\
Ensure to use the link above so you can claim $100 in free credit, to get you started. Plus, when you use that link it helps us out too :D

![Linode's landing page, where you can sign up to get started!](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhnRYvtDHGM4va4ArIY%2F-MhnSqGfTW07BRgJjPFs%2Fimage.png?alt=media\&token=49ec5cd6-f28d-4f11-946d-322f4c0db8a3)

{% hint style="success" %}
Once you've signed up, congratulations! You're set to get your server up and running.
{% endhint %}

## Step 2: Create a Linode Server

We'll be utilizing Docker in order to streamline the process of sending updates to your server.\
To make our lives easier, we'll be creating a server with docker pre-installed, thanks to Linode's nifty Marketplace.

### The Marketplace

{% hint style="info" %}
Make sure you're currently logged in at Linode's dashboard, at <https://cloud.linode.com/>
{% endhint %}

Start by selecting **Marketplace** on the sidebar of Linode's dashboard.

![Where to find the marketplace](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhnRYvtDHGM4va4ArIY%2F-MhnVRYc6fx9pNFFMS-x%2Fimage.png?alt=media\&token=64c14a4b-d6a4-4339-ae94-70f50128ad01)

### Choosing the Docker App

The Docker App consists of a ready-to-go server with Docker pre-installed. This'll save us the trouble of installing Docker manually, as it's all set-up.

**In the Marketplace, look for the Docker App and click on it.**

![Selecting the Docker App in the Marketplace](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhnRYvtDHGM4va4ArIY%2F-MhnWUb9PyV7p8GrNyFw%2Fimage.png?alt=media\&token=6276017b-ad34-4b2a-97c1-7ca169192304)

You'll notice that at the top-left of the panel, we're actually Creating a Linode.\
Linodes are pretty much Virtual Private Servers.

### Configuring the Server

Scroll down past the Advanced Options (we won't need them for this tutorial), and **select Debian 10 as your server's image**. This will ensure that Docker will be installed on the latest supported Debian Operating system. If at the time that you're reading this, there's a newer version of Debian, then I'd highly suggest you choose that instead, to stay up-to-date.

![Selecting the Debian 10 Server Image](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhnYAD25hhcdwEtE12w%2F-MhowwiHlCNfKTtq9MDu%2Fimage.png?alt=media\&token=ecc5777b-0979-4f1b-8665-842e7d8a2082)

Next, **Select a Region**. This depends on where you are located - it's often best to choose the server region closest to you, to reduce latency. In my case, since the Frankfurt datacenters are closest to me, I'll be selecting Frankfurt, DE.

![Selecting your Linode's datacenter location](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhoxE_DshxLX0gkrsbU%2F-MhoxweMCZf_LtcW-OM4%2Fimage.png?alt=media\&token=7946167d-4efb-47f1-b2ba-6fb094b0aeaf)

{% hint style="info" %}
It's a good idea to use Linode's [speedtest page](https://www.linode.com/speedtest) to determine which datacenters would be most suitable with the lowest ping, based on your location.
{% endhint %}

Now, you can choose your plan.\
Linode offers a wide range of many server specifications, built so you can scale whenever necessary.\
We'll be choosing the $5/mo Shared CPU plan, to get started. Note that you can always upgrade/downgrade your plan and scale your server accordingly at any time, even after creating your server.

![Choosing your Linode Plan](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhoxE_DshxLX0gkrsbU%2F-MhozYx1ulzmI8lZejyN%2Fimage.png?alt=media\&token=c28471b7-d27e-4375-8c6c-50a759237429)

#### Server Customization

Set a label and Tag(s) for your Linode. These don't really matter - it's just to keep everything clean and organised.

![Setting a Label and adding Tag(s) to your Linode](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhoxE_DshxLX0gkrsbU%2F-Mhp-hDVlErP_Lk089Zg%2Fimage.png?alt=media\&token=360ea88d-c9e2-462e-bfd0-5bfeff6fee82)

#### Server Security

Now's the time to set your Root Password and SSH key(s) to your Linode. You'll be using the Root Password to log in to your Linode, in case you lose access to your SSH Key. You'll also be prompted to enter this password if you're trying to perform any actions with `sudo`.\
SSH keys are optional, but recommended for additional security.\
To create an SSH Key, simply follow the quick guide [here](/sponsorships/linode-bot-hosting/creating-an-ssh-key).

![Setting a Root Password and Adding an SSH Key](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhoxE_DshxLX0gkrsbU%2F-Mhp0VwJKmjxbGz7KkSt%2Fimage.png?alt=media\&token=36aaee72-4064-4dc0-9368-fdab5d247ece)

#### (Optional) Server Backups

You can optionally enable server backups for your server for an additional $2/mo.\
I'd recommend enabling them, to ensure that your data is protected and backed up, should anything go wrong and you need to roll back your server.\
Better safe than sorry 😅

![Enabling Backups (Optional)](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhp3QAUGy72zK6y0ECX%2F-Mhp4E98lGWD0Mt6hUot%2Fimage.png?alt=media\&token=29695b40-0aee-4988-9c1d-2c32c236f292)

{% hint style="info" %}
There's no need to enable a Private IP yet, but it might come in handy if you're planning on scaling your bot between multiple servers - you won't have to connect to the internet to communicate if both servers are at the same datacenter location.
{% endhint %}

#### Private IP

It's recommended to enable the Private IP for no additional cost.

![](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhp4XCyNZJIWNu7Hzpj%2F-Mhp5JtFoalNFEaZaxmR%2Fimage.png?alt=media\&token=4d7ea69c-9ac6-4968-9e05-166789401161)

{% hint style="success" %}
That's all! Finally, click on **Create Linode** to start provisioning your server.
{% endhint %}

![Click on Create Linode to get your server up and running](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhp5NHUrD08QfbKVogI%2F-Mhp69byu8FQc_2Aalyi%2Fimage.png?alt=media\&token=40523073-ff24-4926-a407-943f114bb6ca)

{% hint style="success" %}
Congratulations on creating your first Linode!\
You should now see that your Linode is being Provisioned and will shortly start Booting!
{% endhint %}

![Linode Provisioning and Booting the Server](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhp5NHUrD08QfbKVogI%2F-Mhp6cUrmPaNsUEe7laQ%2Fimage.png?alt=media\&token=43da6be2-fd49-477b-9fa0-0e4f462036a6)

Once your server is ready, you should see the RUNNING status on your Linode's overview

![Here's what your server should look like after a successful setup](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhr5UGmXas4QDCt3tJa%2F-Mhr6sG61zNPMQDC-hFi%2Fimage.png?alt=media\&token=c919431c-a55e-4455-9431-c5fbcfa13e16)

## Step 3: Creating a Docker Image

If you've already created a docker image, you can skip this part of the tutorial and go straight to [**Step 4: Pulling the Docker Image**](/sponsorships/linode-bot-hosting#step-4-pulling-the-docker-image).\
If not, follow along as I show you how to create yourself a docker image and push it to the Docker Hub.

### Installing Docker Desktop

Visit [Docker's website](https://www.docker.com/products/docker-desktop) to download Docker Desktop on your device.\
Once installed, launch Docker Desktop. It may take some time for the Docker Engine to startup for the first time. **Make sure to signup to Docker Hub, and skip the Tutorial, if prompted.**\
You should then see a screen similar to this one:

![The Docker Desktop Client](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhr5UGmXas4QDCt3tJa%2F-Mhr8n450_PIwuGvfmOP%2Fimage.png?alt=media\&token=0ab366d0-af33-4d1f-887c-10ec62d19a9a)

### Configuring the Dockerfile

In your favorite editor, create a new file called `dockerfile` in the root of your project's folder. We'll be using this file to provide Docker with instructions on what to do when building your Docker Image.

![Creating your dockerfile](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhrJFpNuQbnpxD4nH6P%2F-MhtnaFeXxN7-yNn0c9H%2Fimage.png?alt=media\&token=27737f1c-779a-4285-967b-91c43fb38d1e)

Let's start by specifying a docker baseImage. Think of this as a pre-built docker image from the Docker registry which we can use as a base for our project. Since our bot relies on NodeJS, we'll be using the officially supported `node:slim` NodeJS baseImage.\
Note that we use the **slim** node package, which is a more slimmed-down, optimized version of node ideal for production environments which takes up less storage too.\
**Enter the code `FROM node:slim` in the first line of your dockerfile to specify our baseImage.**

{% code title="dockerfile" %}

```javascript
FROM node:slim
```

{% endcode %}

Next, we'll need to add our app's source code to the Image. To do this, we'll be using the `WORKDIR` working directory instruction.\
**Enter the code `WORKDIR /app` on the next line of your dockerfile to specify our working directory. Any subsequent instructions in our dockerfile will start from this app directory.**

{% code title="dockerfile" %}

```javascript
FROM node:slim

WORKDIR /app
```

{% endcode %}

Let's install our dependencies next, so they can be cached. This will prevent the fuss of having to re-install all our node\_modules every time we change our app's source code. Let's use the `COPY` instruction, which takes two arguments: Our local package.json location, and the place we want to copy it in the container (which is the current working directory).\
**Enter the code `COPY package*.json ./` in the next line of your dockerfile to do this.**

{% code title="dockerfile" %}

```javascript
FROM node:slim

WORKDIR /app

COPY package*.json ./
```

{% endcode %}

Now that we have a package.json, we can run the npm install command. This is just like opening a terminal session and running a command.\
**Enter the code `RUN npm install` in the next line of your dockerfile.**

{% code title="dockerfile" %}

```javascript
FROM node:slim

WORKDIR /app

COPY package*.json ./

RUN npm install
```

{% endcode %}

When finished, the results will be committed to the docker image as a layer. Now that we have our modules in the image, we can then copy over our source code, which we'll do by copying all of our local files into our current working directory.\
**Enter the code `COPY . .` in the next line of your dockerfile.**

{% code title="dockerfile" %}

```javascript
FROM node:slim

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .
```

{% endcode %}

Now, you may be asking, won't that also copy over our `node_modules` folder? You're right. We don't want this, as the `node_modules` folder here in our local filesystem, that would also be copied over to the image and override the `node_modules` that we install there.

**To avoid this, we'll be creating a `.dockerignore` file & add `node_modules` as well as .env to it.**\
It works just like a `.gitignore` file, which you've probably seen before.\
Here's what your `.dockerignore` file should look like:

{% code title=".dockerignore" %}

```javascript
node_modules
.env
```

{% endcode %}

{% hint style="warning" %}
Add .env in .dockerignore only if you use dotenv for secret management!
{% endhint %}

So at this point, we have our source code in the image. But in order to run it we'll be using the keyword `COMMAND`. there can only be one of these for every dockerfile, and it tells the container how to run the actual application.\
**Enter the code `CMD [ "npm", "start" ]`  in the next line of your dockerfile.**

{% code title="dockerfile" %}

```javascript
FROM node:slim

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

CMD [ "npm", "start" ]
```

{% endcode %}

You'll also notice that unlike `RUN` we've made this command an array of strings. This is known as exec form, and it's the preferred way to do things. **Unlike a regular command, it doesn't start up a shell session.**

#### Resulting Dockerfile

Here's what our final dockerfile should look like:

<figure><img src="https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MhnK0SlNFUfBHuu-EZn%2Fuploads%2FjsS5Sy3qbFf6sROkk6ts%2Fimage.png?alt=media&amp;token=ae0b793d-e5c1-4e5f-a54e-895c59344a4c" alt=""><figcaption><p>Here's what our completed dockerfile should look like.</p></figcaption></figure>

### Creating a Docker Image

Start by opening a terminal in your favorite code editor, and enter the command below to build a Docker Image:

```javascript
docker build -t yourUsername/coolbot:1.0 .
```

**The command is docker build, and we pass the option -t in order to add a nametag to your image that's easy to remember, so you can access it later. When defining the tag name, it's recommended to enter your username followed by `/imagename:version.number .`**\
**You should also add a version number, separated by a colon. From there you simply add the path to your dockerfile, which in our case is just a `.` for the current working directory.**

Hit enter to run the command, and you'll notice that it starts with Step 1, which is to pull the node:slim image remotely. Then it goes through each step in our dockerfile, and it should finally say `successfully built [image ID]`.

### Pushing the Image

Before we begin, it's a good idea to set the default visibility of our Docker Repositories to private. This'll help keep our environment variables and any code which explicitly states our bot's token secure.\
**To set our Default Repository Visibility to Private, go to the** [**Docker Hub**](https://hub.docker.com/) **> Account Settings > Default Privacy, then select Private as your Default Repository Visibility. Lastly, click on Save.**

![Setting the Default Repository Visibility to Private](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-Mhu8PkVqTtkGS5CwmYZ%2F-MiNqo4Eq31WDz3J_65N%2Fimage.png?alt=media\&token=4b148926-3f81-4644-a1db-2ab48c6cfb40)

{% hint style="warning" %}
**Note that the Docker Hub offers just one private repository on the free tier.**\
To get more, you'll have to upgrade. However, you can always work around this in the future by either [creating and hosting your own docker registry](https://docs.docker.com/registry/deploying/), or by using alternatives to Docker Hub, such as the [GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/).
{% endhint %}

We're all set! Let's push this Image.

To push the Docker Image, let's first make sure you're logged in to the Docker Registry on the terminal.\
To login, open a new terminal and enter the command `docker login`.

```javascript
docker login
```

You'll be prompted to enter your credentials (Username and Password). When entering the password, it may seem as though no text is being entered, but rest assured it's being entered (this is a security feature).

**Once you've typed in your Username and Password, hit enter once more and you should be good to go.**

{% hint style="info" %}
Once logged in, you may get a security warning about your password being stored unencrypted, but you can safely ignore it.
{% endhint %}

#### Tagging the Image as Latest Release \[Recommended]

In order to push our Image to the Docker Hub, it's always best practice to tag the image as the latest release of our program (in this case our bot).\
To do this, we'll use the `docker image tag` command:

```javascript
docker image tag yourUsername/coolbot:1.0 yourUsername/coolbot:latest
```

You'll notice that we enter `docker image tag` followed by the **same Image tag** as we gave it in the previous step, after which we enter the new tag we want to assign to this Docker Image. In this case, it's the same **`[username]/[imagename]`**, followed by a colon for the version number, where we enter **`latest`**.\
This'll allow us to easily push updates in the future, by assigning the **`:latest`** tag to newer versions of the bot when we want to publish changes / an update to our bot's code.\
**In the future, we'll be able to pull and run just the latest version of the code, instead of having to manually pull each version separately, look for the latest version, and run that, again and again.**

#### Let's Push

It's time to finally Push the Image to the Docker Registry.\
Simply enter and run the command `docker push yourUsername/coolbot:latest`

```javascript
docker push yourUsername/coolbot:latest
```

The Docker Image should start pushing to the Registry. This'll take some time, depending on your network speed (usually takes around 5-10 minutes for my bot).

{% hint style="success" %}
Nice job! We're almost there. Feel free to enjoy your favorite drink and take a quick break.
{% endhint %}

## Step 4: Pulling the Docker Image

Now that the image is safely on the Docker Registry, we're ready to pull it and download it to our Linode server.

### Logging in to our Linode Server

To begin, get your server's public IP Address via the [Linode Cloud Dashboard](https://cloud.linode.com/linodes). Select your newly created Linode server (from [Step 2](/sponsorships/linode-bot-hosting#step-2-create-a-linode-server)), and in the overview copy the Server's IPv4 Address:

![Copying our server's IPv4 Address](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MiNzcdvDkGt6BPguqUi%2F-MiO-4Y-6P0Km6B8aMRX%2Fimage.png?alt=media\&token=be0c45d4-172f-4045-84fd-fc66afe01ec2)

Next, open a new terminal and enter the command **`ssh root@[your server IP]`**.\
Make sure to enter your server's IPv4 Address which you had just copied right after the `@` symbol.\
Here's what my command looks like:

```bash
ssh root@172.104.133.229

(make sure to replace 172.104.133.229 with your server's IPv4 Address)
```

{% hint style="warning" %}
You may receive a warning stating that the authenticity of the host can't be established.\
This is for security, and you must enter **`yes`** and hit enter to allow the connection to be established.
{% endhint %}

![Authenticity of host warning](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MiO-Ljf44afgor7b9no%2F-MiO1u5l7GhqYhmZqdzD%2Fimage.png?alt=media\&token=ca3b0b42-bbd3-424b-9ab3-d3c05c88fd81)

If your SSH key is detected, you should log in straight away into your Linode Server! If you haven't created an SSH key, you'll be prompted to enter your Linode Server's password (which you set [here](/sponsorships/linode-bot-hosting#configuring-the-server)).

### Logging in to Docker

In order to access our private Docker Registry, we'll need to login with our docker Username and Password. **To login, we'll (once again) enter the command `docker login`, and follow the instructions prompted.**

```bash
docker login
```

![Logging in to Docker](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MiO3nbYvqKs2MMp7874%2F-MiO4BQSMKXn8AYLhW8x%2Fimage.png?alt=media\&token=2a998d91-439a-410c-a682-eddd2a253a17)

{% hint style="info" %}
Once logged in, you may get a security warning about your password being stored unencrypted, but you can safely ignore it.
{% endhint %}

### Pulling the Image

To pull the Image from our private Docker Repository, simply enter the command `docker pull yourUsername/coolbot:latest`

```bash
docker pull yourUsername/coolbot:latest
```

![Pulling the Image from our private Docker Repository](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MiO4SEA2y01JjiAHzcL%2F-MiO5-QxpIoRIeoe00nC%2Fimage.png?alt=media\&token=cb17f08d-8bd2-453d-afd7-2ddd8c6b01a7)

You should now see all the different layers of our Image download, after which the Pull will Complete.

## Step 5: Running the Docker Image 24/7

When paired with Linode's Shutdown Watchdog (also known as Lassie), all we need to do is run our Docker Image and set it to start back up on boot, using two simple commands.

### Getting our Image ID

To get our Docker Image's ID, simply enter the command `docker images` and copy the IMAGE ID.

```bash
docker images
```

![Copy the Image ID, as underlined.](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MiO4SEA2y01JjiAHzcL%2F-MiO73qSPAWb_OfVQTkL%2Fimage.png?alt=media\&token=c4d29b63-2b30-485a-9b41-e6610f644555)

**Finally, to run the Image and configure it to run automatically on boot, execute this command:**\
**`docker run -d --restart always [IMAGE ID]`**

{% code title="(make sure to replace 7ea5c0aa7ab5 with your IMAGE ID)" %}

```bash
 docker run -d --restart always 7ea5c0aa7ab5
```

{% endcode %}

This'll run your Image, and set it to always restart, regardless of the cause of the program stopping/crashing.\
As the Docker Docs say, using the flag `always` indicates to:

| <p>Always restart the container if it stops. If it is manually stopped, it is restarted only when Docker daemon restarts or the container itself is manually restarted.<br><strong>Source:</strong> <a href="https://docs.docker.com/config/containers/start-containers-automatically/"><strong><https://docs.docker.com/config/containers/start-containers-automatically/></strong></a></p> |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% hint style="success" %}
**...and that's all - your bot should be online and ready to go! Congrats!**\
**To logout of your server, simply enter the command `logout`.**
{% endhint %}

## Handy Commands

* **To login to your server, simply enter `ssh root@[IPv4]`.**
* **To view your currently running containers, simply enter `docker ps`.**
* **To view your currently pulled Images, simply enter `docker images`.**
* **To stop a currently running container, simply enter `docker stop [IMAGE ID]`.**
* **To run an Image and configure it to run automatically on boot, execute this command:**\
  **`docker run -d --restart always [IMAGE ID]`.**
* **To logout of your server, simply enter the command `logout`.**


# Creating an SSH Key

An SSH key is an access credential for the SSH (secure shell) network protocol. This authenticated and encrypted secure network protocol is used for remote communication between machines.

Follow these instructions to create or add SSH keys on Linux, MacOS & Windows.

## Create a new key pair, if needed

To create an SSH Key, open a terminal and run the following command:

```
ssh-keygen
```

You will be prompted to save and name the key.

```
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/USER/.ssh/id_rsa):
```

Next, you will be asked to create and confirm a passphrase for the key (highly recommended):

```
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

&#x20;This will generate two files, by default called `id_rsa` and `id_rsa.pub`. Next, add this public key.

## Add the public key

Copy and paste the contents of the **.pub** file, typically id\_rsa.pub, into the **SSH Public Key** field.

```
cat ~/.ssh/id_rsa.pub
```

{% hint style="info" %}
You don't need to use this command - you can simply right-click the id\_rsa.pub file and open it with your favorite IDE and copy the contents from there into the **SSH Public Key** field.
{% endhint %}

Your public (.pub) SSH Key should look something like this:

![](https://3594988393-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhnK0SlNFUfBHuu-EZn%2F-MhoxE_DshxLX0gkrsbU%2F-Mhp2to2HqAm3uvKNvza%2Fimage.png?alt=media\&token=ddf84234-14d5-4621-af08-e85faca2b59a)


