Skip to content

Commit

Permalink
Merge #4: New example config for a dropplet
Browse files Browse the repository at this point in the history
c989795 feat: [#2] new example config for dropplet (Jose Celano)

Pull request description:

  Example production compose configuration to run Torrust on a Digital Ocean droplet with:

  - SQLite.
  - Let's Encrypt (HTTPs). Auto-renewal of certificates.
  - No firewall rules. Digital Ocean Firewall service could be enabled.

ACKs for top commit:
  josecelano:
    ACK c989795

Tree-SHA512: 22d3c98c430b6bc8eceac03003e6afe9b93441fe861f254f6040f8d09099c992541d92d0b38d74f68f43150c5e300cb45b94c703ff34364d78d66f151d175b06
  • Loading branch information
josecelano committed Dec 14, 2023
2 parents 87c7884 + c989795 commit 164827f
Show file tree
Hide file tree
Showing 15 changed files with 758 additions and 0 deletions.
15 changes: 15 additions & 0 deletions droplet/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
USER_ID=1000

# Index GUI
TORRUST_INDEX_GUI_API_BASE_URL='http://index.torrust-demo.com/api/v1'
NITRO_HOST="0.0.0.0"
NITRO_PORT=3000

# Index
TORRUST_INDEX_CONFIG=
TORRUST_INDEX_TRACKER_API_TOKEN='MyAccessToken'
TORRUST_INDEX_API_CORS_PERMISSIVE=false

# Tracker
TORRUST_TRACKER_CONFIG=
TORRUST_TRACKER_API_ADMIN_TOKEN='MyAccessToken'
3 changes: 3 additions & 0 deletions droplet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.env
.storage/
storage/
232 changes: 232 additions & 0 deletions droplet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# Droplet configuration

It's a sample production configuration to deploy the Index on a Digital Ocean droplet.

Please, refer to each project's README for more information about how to run them using docker.

## Requirements

- Docker version 24.0.7, build afdd53b.
- Docker Compose version v2.3.3.
- GNU bash, version 5.2.15(1)-release (x86_64-pc-linux-gnu).

## Install

Follow instructions from: <https://www.digitalocean.com/community/tutorials/how-to-secure-a-containerized-node-js-application-with-nginx-let-s-encrypt-and-docker-compose>.

We will publish an article on the <https://torrust.com/blog> with a detailed description of
the installation process.

```console
mkdir ~/Tmp && cd ~/Tmp
git clone [email protected]:torrust/torrust-compose.git
cd torrust-compose/droplet
./bin/install.sh
```

Edit the `.env` file to change the default Tracker API token:

```console
TORRUST_INDEX_TRACKER_API_TOKEN="your_secret_token"
TORRUST_TRACKER_API_ADMIN_TOKEN="your_secret_token"
```

### HTTPS

Get certificates:

Log into the `certbot` container:

```console
docker com1pose run --entrypoint /bin/sh certbot
```

Get staging certificates:

```console
certbot certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --staging -d index.torrust-demo.com
certbot certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --staging -d tracker.torrust-demo.com
```

Get production certificates:

```console
certbot certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d index.torrust-demo.com
certbot certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d tracker.torrust-demo.com
```

Check that the proxy can see the certificates:

```console
docker compose exec proxy ls -la /etc/letsencrypt/live
```

Generate your key with the openssl command:

```console
sudo openssl dhparam -out /home/torrust/github/josecelano/torrust-compose/droplet/storage/dhparam/dhparam-2048.pem 2048
```

Edit the Nginx config file:

```console
vim ./storage/proxy/etc/nginx-conf/nginx.conf
```

Uncomment the lines for HTTPS servers and recreate the proxy with:

```console
docker compose up -d --force-recreate --no-deps proxy
```

Edit the `.env` file changing the API base URL to use HTTPS:

```console
TORRUST_INDEX_GUI_API_BASE_URL='https://index.torrust-demo.com/api/v1'
```

Add the following cronjob with `sudo crontab -e` to auto-renew certificates:

```text
0 12 * * * /home/torrust/github/torrust/torrust-compose/droplet/bin/ssl_renew.sh >> /var/log/cron.log 2>&1
```

You can check the cronjob output with `tail -n 200 /var/log/cron.log`.

### Storage

This is how the storage folder is configured after installation (including HTTPS).

```console
$ sudo tree storage
storage
├── certbot
│   ├── etc
│   │   ├── accounts
│   │   │   ├── acme-staging-v02.api.letsencrypt.org
│   │   │   │   └── directory
│   │   │   │   └── b39c03e978384cf4e136df8366ab6539
│   │   │   │   ├── meta.json
│   │   │   │   ├── private_key.json
│   │   │   │   └── regr.json
│   │   │   └── acme-v02.api.letsencrypt.org
│   │   │   └── directory
│   │   │   └── 441a435b0f8057dfd96cc6dd22f34468
│   │   │   ├── meta.json
│   │   │   ├── private_key.json
│   │   │   └── regr.json
│   │   ├── archive
│   │   │   ├── index.torrust-demo.com
│   │   │   │   ├── cert1.pem
│   │   │   │   ├── chain1.pem
│   │   │   │   ├── fullchain1.pem
│   │   │   │   └── privkey1.pem
│   │   │   ├── index.torrust-demo.com-0001
│   │   │   │   ├── cert1.pem
│   │   │   │   ├── cert2.pem
│   │   │   │   ├── chain1.pem
│   │   │   │   ├── chain2.pem
│   │   │   │   ├── fullchain1.pem
│   │   │   │   ├── fullchain2.pem
│   │   │   │   ├── privkey1.pem
│   │   │   │   └── privkey2.pem
│   │   │   └── tracker.torrust-demo.com
│   │   │   ├── cert1.pem
│   │   │   ├── cert2.pem
│   │   │   ├── cert3.pem
│   │   │   ├── chain1.pem
│   │   │   ├── chain2.pem
│   │   │   ├── chain3.pem
│   │   │   ├── fullchain1.pem
│   │   │   ├── fullchain2.pem
│   │   │   ├── fullchain3.pem
│   │   │   ├── privkey1.pem
│   │   │   ├── privkey2.pem
│   │   │   └── privkey3.pem
│   │   ├── live
│   │   │   ├── README
│   │   │   ├── index.torrust-demo.com
│   │   │   │   ├── README
│   │   │   │   ├── cert.pem -> ../../archive/index.torrust-demo.com/cert1.pem
│   │   │   │   ├── chain.pem -> ../../archive/index.torrust-demo.com/chain1.pem
│   │   │   │   ├── fullchain.pem -> ../../archive/index.torrust-demo.com/fullchain1.pem
│   │   │   │   └── privkey.pem -> ../../archive/index.torrust-demo.com/privkey1.pem
│   │   │   ├── index.torrust-demo.com-0001
│   │   │   │   ├── README
│   │   │   │   ├── cert.pem -> ../../archive/index.torrust-demo.com-0001/cert2.pem
│   │   │   │   ├── chain.pem -> ../../archive/index.torrust-demo.com-0001/chain2.pem
│   │   │   │   ├── fullchain.pem -> ../../archive/index.torrust-demo.com-0001/fullchain2.pem
│   │   │   │   └── privkey.pem -> ../../archive/index.torrust-demo.com-0001/privkey2.pem
│   │   │   └── tracker.torrust-demo.com
│   │   │   ├── README
│   │   │   ├── cert.pem -> ../../archive/tracker.torrust-demo.com/cert3.pem
│   │   │   ├── chain.pem -> ../../archive/tracker.torrust-demo.com/chain3.pem
│   │   │   ├── fullchain.pem -> ../../archive/tracker.torrust-demo.com/fullchain3.pem
│   │   │   └── privkey.pem -> ../../archive/tracker.torrust-demo.com/privkey3.pem
│   │   ├── renewal
│   │   │   ├── index.torrust-demo.com-0001.conf
│   │   │   ├── index.torrust-demo.com.conf
│   │   │   └── tracker.torrust-demo.com.conf
│   │   └── renewal-hooks
│   │   ├── deploy
│   │   ├── post
│   │   └── pre
│   └── lib
├── dhparam
│   └── dhparam-2048.pem
├── index
│   ├── etc
│   │   └── index.toml
│   ├── lib
│   │   └── database
│   │   └── sqlite3.db
│   └── log
├── index-gui
│   └── log
├── proxy
│   ├── etc
│   │   └── nginx-conf
│   │   ├── nginx.conf
│   │   └── nginx.conf.bak
│   └── webroot
└── tracker
├── etc
│   └── tracker.toml
├── lib
│   └── database
│   └── sqlite3.db
└── log

40 directories, 56 files
```

## Usage

To start the application:

```s
./bin/start.sh
```

To stop the application:

```s
./bin/stop.sh
```

By default, the application will:

- Be available at <http://localhost:3000>.
- Use the `./storage` directory to store the data.
- Use SQLite as the database engine.

After starting the application you should see these running containers:

```s
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fbed1b994c7a nginx:mainline-alpine "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp proxy
5d8e6fb74102 torrust/index-gui:develop "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes (healthy) 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp index-gui
60854e389bb7 torrust/index:develop "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes (healthy) 0.0.0.0:3001->3001/tcp, :::3001->3001/tcp index
16b1a40d96f9 torrust/tracker:develop "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes (healthy) 0.0.0.0:1212->1212/tcp, :::1212->1212/tcp, 0.0.0.0:7070->7070/tcp, :::7070->7070/tcp, 1313/tcp, 0.0.0.0:6969->6969/udp, :::6969->6969/udp tracker
```
56 changes: 56 additions & 0 deletions droplet/bin/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash

if ! [ -f "./.env" ]; then
echo "Creating compose .env './.env'"
cp .env.production .env
fi

## Proxy

mkdir -p ./storage/proxy/etc/nginx-conf
mkdir -p ./storage/proxy/webroot
mkdir -p ./storage/dhparam

if ! [ -f "./storage/proxy/etc/nginx-conf/nginx.conf" ]; then
echo "Creating proxy config file: './storage/proxy/etc/nginx-conf/nginx.conf'"
cp ./share/container/default/config/nginx.conf ./storage/proxy/etc/nginx-conf/nginx.conf
fi

## Certbot

mkdir -p ./storage/certbot/etc
mkdir -p ./storage/certbot/lib

## Index

# Generate the Index sqlite database directory and file if it does not exist
mkdir -p ./storage/index/lib/database

if ! [ -f "./storage/index/lib/database/sqlite3.db" ]; then
echo "Creating index database: './storage/index/lib/database/sqlite3.db'"
sqlite3 "./storage/index/lib/database/sqlite3.db" "VACUUM;"
fi

mkdir -p ./storage/index/etc

if ! [ -f "./storage/index/etc/index.prod.container.sqlite3.toml" ]; then
echo "Crating index configuration: './storage/index/etc/index.toml'"
cp ./share/container/default/config/index.prod.container.sqlite3.toml ./storage/index/etc/index.toml
fi

## Tracker

# Generate the Tracker sqlite database directory and file if it does not exist
mkdir -p ./storage/tracker/lib/database

if ! [ -f "./storage/tracker/lib/database/sqlite3.db" ]; then
echo "Creating tracker database: './storage/tracker/lib/database/sqlite3.db'"
sqlite3 "./storage/tracker/lib/database/sqlite3.db" "VACUUM;"
fi

mkdir -p ./storage/tracker/etc

if ! [ -f "./storage/tracker/etc/tracker.prod.container.sqlite3.toml" ]; then
echo "Crating tracker configuration: './storage/tracker/etc/tracker.toml'"
cp ./share/container/default/config/tracker.prod.container.sqlite3.toml ./storage/tracker/etc/tracker.toml
fi
7 changes: 7 additions & 0 deletions droplet/bin/restart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

TORRUST_INDEX_CONFIG_PATH=$(cat ./storage/index/etc/index.toml) \
TORRUST_TRACKER_CONFIG_PATH=$(cat ./storage/tracker/etc/tracker.toml) \
TORRUST_TRACKER_API_ADMIN_TOKEN=${TORRUST_TRACKER_API_ADMIN_TOKEN:-MyAccessToken} \
TORRUST_INDEX_TRACKER_API_TOKEN=${TORRUST_INDEX_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose restart
7 changes: 7 additions & 0 deletions droplet/bin/restart_proxy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

TORRUST_INDEX_CONFIG_PATH=$(cat ./storage/index/etc/index.toml) \
TORRUST_TRACKER_CONFIG_PATH=$(cat ./storage/tracker/etc/tracker.toml) \
TORRUST_TRACKER_API_ADMIN_TOKEN=${TORRUST_TRACKER_API_ADMIN_TOKEN:-MyAccessToken} \
TORRUST_INDEX_TRACKER_API_TOKEN=${TORRUST_INDEX_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose --ansi never restart proxy
15 changes: 15 additions & 0 deletions droplet/bin/ssl_renew.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

COMPOSE="/usr/bin/docker compose --ansi never"
DOCKER="/usr/bin/docker"

cd /home/torrust/github/torrust/torrust-compose/droplet || exit

# Run this just for testing purposes
#$COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP proxy

# Renew certificates that are close to expiring and restart proxy server
# to reload Nginx congiuration.
$COMPOSE run certbot renew && ./bin/restart_proxy.sh

$DOCKER system prune -af
7 changes: 7 additions & 0 deletions droplet/bin/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

TORRUST_INDEX_CONFIG_PATH=$(cat ./storage/index/etc/index.toml) \
TORRUST_TRACKER_CONFIG_PATH=$(cat ./storage/tracker/etc/tracker.toml) \
TORRUST_TRACKER_API_ADMIN_TOKEN=${TORRUST_TRACKER_API_ADMIN_TOKEN:-MyAccessToken} \
TORRUST_INDEX_TRACKER_API_TOKEN=${TORRUST_INDEX_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose up --build --detach
3 changes: 3 additions & 0 deletions droplet/bin/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

docker compose down
5 changes: 5 additions & 0 deletions droplet/bin/update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

./bin/stop.sh
docker compose pull
./bin/start.sh
Loading

0 comments on commit 164827f

Please sign in to comment.