Docker
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
FROM postgres:11.3
|
||||
|
||||
COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance
|
||||
RUN chmod +x /usr/local/bin/maintenance/*
|
||||
RUN mv /usr/local/bin/maintenance/* /usr/local/bin \
|
||||
&& rmdir /usr/local/bin/maintenance
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
BACKUP_DIR_PATH='/backups'
|
||||
BACKUP_FILE_PREFIX='backup'
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
countdown() {
|
||||
declare desc="A simple countdown. Source: https://superuser.com/a/611582"
|
||||
local seconds="${1}"
|
||||
local d=$(($(date +%s) + "${seconds}"))
|
||||
while [ "$d" -ge `date +%s` ]; do
|
||||
echo -ne "$(date -u --date @$(($d - `date +%s`)) +%H:%M:%S)\r";
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
message_newline() {
|
||||
echo
|
||||
}
|
||||
|
||||
message_debug()
|
||||
{
|
||||
echo -e "DEBUG: ${@}"
|
||||
}
|
||||
|
||||
message_welcome()
|
||||
{
|
||||
echo -e "\e[1m${@}\e[0m"
|
||||
}
|
||||
|
||||
message_warning()
|
||||
{
|
||||
echo -e "\e[33mWARNING\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_error()
|
||||
{
|
||||
echo -e "\e[31mERROR\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_info()
|
||||
{
|
||||
echo -e "\e[37mINFO\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_suggestion()
|
||||
{
|
||||
echo -e "\e[33mSUGGESTION\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_success()
|
||||
{
|
||||
echo -e "\e[32mSUCCESS\e[0m: ${@}"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
yes_no() {
|
||||
declare desc="Prompt for confirmation. \$\"\{1\}\": confirmation message."
|
||||
local arg1="${1}"
|
||||
|
||||
local response=
|
||||
read -r -p "${arg1} (y/[n])? " response
|
||||
if [[ "${response}" =~ ^[Yy]$ ]]
|
||||
then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
### Create a database backup.
|
||||
###
|
||||
### Usage:
|
||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres backup
|
||||
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
working_dir="$(dirname ${0})"
|
||||
source "${working_dir}/_sourced/constants.sh"
|
||||
source "${working_dir}/_sourced/messages.sh"
|
||||
|
||||
|
||||
message_welcome "Backing up the '${POSTGRES_DB}' database..."
|
||||
|
||||
|
||||
if [[ "${POSTGRES_USER}" == "postgres" ]]; then
|
||||
message_error "Backing up as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PGHOST="${POSTGRES_HOST}"
|
||||
export PGPORT="${POSTGRES_PORT}"
|
||||
export PGUSER="${POSTGRES_USER}"
|
||||
export PGPASSWORD="${POSTGRES_PASSWORD}"
|
||||
export PGDATABASE="${POSTGRES_DB}"
|
||||
|
||||
backup_filename="${BACKUP_FILE_PREFIX}_$(date +'%Y_%m_%dT%H_%M_%S').sql.gz"
|
||||
pg_dump | gzip > "${BACKUP_DIR_PATH}/${backup_filename}"
|
||||
|
||||
|
||||
message_success "'${POSTGRES_DB}' database backup '${backup_filename}' has been created and placed in '${BACKUP_DIR_PATH}'."
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
### View backups.
|
||||
###
|
||||
### Usage:
|
||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres backups
|
||||
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
working_dir="$(dirname ${0})"
|
||||
source "${working_dir}/_sourced/constants.sh"
|
||||
source "${working_dir}/_sourced/messages.sh"
|
||||
|
||||
|
||||
message_welcome "These are the backups you have got:"
|
||||
|
||||
ls -lht "${BACKUP_DIR_PATH}"
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
### Restore database from a backup.
|
||||
###
|
||||
### Parameters:
|
||||
### <1> filename of an existing backup.
|
||||
###
|
||||
### Usage:
|
||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres restore <1>
|
||||
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
working_dir="$(dirname ${0})"
|
||||
source "${working_dir}/_sourced/constants.sh"
|
||||
source "${working_dir}/_sourced/messages.sh"
|
||||
|
||||
|
||||
if [[ -z ${1+x} ]]; then
|
||||
message_error "Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again."
|
||||
exit 1
|
||||
fi
|
||||
backup_filename="${BACKUP_DIR_PATH}/${1}"
|
||||
if [[ ! -f "${backup_filename}" ]]; then
|
||||
message_error "No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
message_welcome "Restoring the '${POSTGRES_DB}' database from the '${backup_filename}' backup..."
|
||||
|
||||
if [[ "${POSTGRES_USER}" == "postgres" ]]; then
|
||||
message_error "Restoring as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PGHOST="${POSTGRES_HOST}"
|
||||
export PGPORT="${POSTGRES_PORT}"
|
||||
export PGUSER="${POSTGRES_USER}"
|
||||
export PGPASSWORD="${POSTGRES_PASSWORD}"
|
||||
export PGDATABASE="${POSTGRES_DB}"
|
||||
|
||||
message_info "Dropping the database..."
|
||||
dropdb "${PGDATABASE}"
|
||||
|
||||
message_info "Creating a new database..."
|
||||
createdb --owner="${POSTGRES_USER}"
|
||||
|
||||
message_info "Applying the backup to the new database..."
|
||||
gunzip -c "${backup_filename}" | psql "${POSTGRES_DB}"
|
||||
|
||||
message_success "The '${POSTGRES_DB}' database has been restored from the '${backup_filename}' backup."
|
||||
@@ -0,0 +1,13 @@
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk update \
|
||||
&& apk upgrade \
|
||||
&& apk add tor \
|
||||
&& rm /var/cache/apk/*
|
||||
|
||||
EXPOSE 9150
|
||||
|
||||
ADD ./compose/production/tor/torrc /etc/tor/torrc
|
||||
|
||||
USER tor
|
||||
CMD /usr/bin/tor -f /etc/tor/torrc
|
||||
@@ -0,0 +1,25 @@
|
||||
## The directory for keeping all the keys/etc
|
||||
DataDirectory /var/lib/tor
|
||||
|
||||
## Tor opens a socks proxy on port 9150
|
||||
SocksPort 0.0.0.0:9150
|
||||
|
||||
## Entry policies to allow/deny SOCKS requests based on IP address.
|
||||
## SocksPolicy accept 192.168.1.0/24
|
||||
SocksPolicy accept 172.17.0.0/16
|
||||
SocksPolicy accept 10.0.0.0/8
|
||||
SocksPolicy reject *
|
||||
|
||||
## Logs go to stdout at level "notice"
|
||||
Log notice stdout
|
||||
|
||||
ControlPort 9051
|
||||
|
||||
# Try for at most NUM seconds when building circuits. If the circuit isn't open in that time, give up on it. (Default: 1 minute.)
|
||||
CircuitBuildTimeout 5
|
||||
# Send a padding cell every N seconds to keep firewalls from closing our connections while Tor is not in use.
|
||||
KeepalivePeriod 60
|
||||
# Force Tor to consider whether to build a new circuit every NUM seconds.
|
||||
NewCircuitPeriod 15
|
||||
# How many entry guards should we keep at a time?
|
||||
NumEntryGuards 8
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM traefik:alpine
|
||||
RUN mkdir -p /etc/traefik/acme
|
||||
RUN touch /etc/traefik/acme/acme.json
|
||||
RUN chmod 600 /etc/traefik/acme/acme.json
|
||||
COPY ./compose/production/traefik/traefik.toml /etc/traefik
|
||||
@@ -0,0 +1,176 @@
|
||||
#debug = true
|
||||
|
||||
logLevel = "ERROR" #DEBUG, INFO, WARN, ERROR, FATAL, PANIC
|
||||
InsecureSkipVerify = true
|
||||
|
||||
#defaultEntryPoints = ["http", "https"]
|
||||
defaultEntryPoints = ["http"]
|
||||
|
||||
# Entrypoints, http and https
|
||||
[entryPoints]
|
||||
# http should be redirected to https
|
||||
[entryPoints.http]
|
||||
address = ":80"
|
||||
#[entryPoints.http.redirect]
|
||||
#entryPoint = "https"
|
||||
# https is the default
|
||||
#[entryPoints.https]
|
||||
#address = ":443"
|
||||
# [entryPoints.https.tls]
|
||||
|
||||
## Enable ACME (Let's Encrypt): automatic SSL
|
||||
#[acme]
|
||||
## Email address used for registration
|
||||
#email = "steven@cyber5k.com"
|
||||
#storage = "/etc/traefik/acme/acme.json"
|
||||
#entryPoint = "https"
|
||||
#onDemand = false
|
||||
#OnHostRule = true
|
||||
# # Use a HTTP-01 acme challenge rather than TLS-SNI-01 challenge
|
||||
# [acme.httpChallenge]
|
||||
# entryPoint = "http"
|
||||
|
||||
[file]
|
||||
[backends]
|
||||
[backends.django]
|
||||
[backends.django.servers.server1]
|
||||
url = "http://django:5000"
|
||||
|
||||
[backends.pihole]
|
||||
[backends.pihole.servers.server1]
|
||||
url = "http://pihole:80"
|
||||
|
||||
[backends.homeassistant]
|
||||
[backends.homeassistant.servers.server1]
|
||||
url = "http://homeassistant:8123"
|
||||
|
||||
[backends.syncthing]
|
||||
[backends.syncthing.servers.server1]
|
||||
url = "http://syncthing:8384"
|
||||
|
||||
[backends.rocketchat]
|
||||
[backends.rocketchat.servers.server1]
|
||||
url = "http://rocketchat:3000"
|
||||
|
||||
[backends.nextcloud]
|
||||
[backends.nextcloud.servers.server1]
|
||||
url = "http://nextcloud:80"
|
||||
|
||||
[backends.onlyoffice]
|
||||
[backends.onlyoffice.servers.server1]
|
||||
url = "http://onlyoffice:80"
|
||||
|
||||
[backends.bitwarden]
|
||||
[backends.bitwarden.servers.server1]
|
||||
url = "http://bitwarden:80"
|
||||
|
||||
[backends.jellyfin]
|
||||
[backends.jellyfin.servers.server1]
|
||||
url = "http://jellyfin:8096"
|
||||
|
||||
[backends.raspap]
|
||||
[backends.raspap.servers.server1]
|
||||
url = "http://raspap:80"
|
||||
|
||||
[backends.cockpit]
|
||||
[backends.cockpit.servers.server1]
|
||||
url = "http://IPV4_PUBLIC:9090"
|
||||
|
||||
[frontends]
|
||||
[frontends.django]
|
||||
backend = "django"
|
||||
passHostHeader = true
|
||||
[frontends.django.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.django.routes.dr1]
|
||||
#rule = "Host:mistborn.cyber5k.com"
|
||||
rule = "Host:home.mistborn"
|
||||
|
||||
[frontends.pihole]
|
||||
backend = "pihole"
|
||||
passHostHeader = true
|
||||
[frontends.pihole.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.pihole.routes.dr1]
|
||||
rule = "Host:pihole.mistborn"
|
||||
|
||||
[frontends.homeassistant]
|
||||
backend = "homeassistant"
|
||||
passHostHeader = true
|
||||
[frontends.homeassistant.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.homeassistant.routes.dr1]
|
||||
rule = "Host:hass.mistborn"
|
||||
|
||||
[frontends.syncthing]
|
||||
backend = "syncthing"
|
||||
passHostHeader = true
|
||||
[frontends.syncthing.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.syncthing.routes.dr1]
|
||||
rule = "Host:syncthing.mistborn"
|
||||
|
||||
[frontends.rocketchat]
|
||||
backend = "rocketchat"
|
||||
passHostHeader = true
|
||||
[frontends.rocketchat.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.rocketchat.routes.dr1]
|
||||
rule = "Host:chat.mistborn"
|
||||
|
||||
[frontends.nextcloud]
|
||||
backend = "nextcloud"
|
||||
passHostHeader = true
|
||||
[frontends.nextcloud.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.nextcloud.routes.dr1]
|
||||
rule = "Host:nextcloud.mistborn"
|
||||
|
||||
[frontends.onlyoffice]
|
||||
backend = "onlyoffice"
|
||||
passHostHeader = true
|
||||
[frontends.onlyoffice.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.onlyoffice.routes.dr1]
|
||||
rule = "Host:onlyoffice.mistborn"
|
||||
|
||||
[frontends.bitwarden]
|
||||
backend = "bitwarden"
|
||||
passHostHeader = true
|
||||
[frontends.bitwarden.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.bitwarden.routes.dr1]
|
||||
rule = "Host:bitwarden.mistborn"
|
||||
|
||||
[frontends.jellyfin]
|
||||
backend = "jellyfin"
|
||||
passHostHeader = true
|
||||
[frontends.jellyfin.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.jellyfin.routes.dr1]
|
||||
rule = "Host:jellyfin.mistborn"
|
||||
|
||||
[frontends.raspap]
|
||||
backend = "raspap"
|
||||
passHostHeader = true
|
||||
[frontends.raspap.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.raspap.routes.dr1]
|
||||
rule = "Host:raspap.mistborn"
|
||||
|
||||
[frontends.cockpit]
|
||||
backend = "cockpit"
|
||||
passHostHeader = true
|
||||
[frontends.cockpit.headers]
|
||||
HostsProxyHeaders = ['X-CSRFToken']
|
||||
[frontends.cockpit.routes.dr1]
|
||||
rule = "Host:cockpit.mistborn"
|
||||
|
||||
## Connection to docker host system (docker.sock)
|
||||
#[docker]
|
||||
#endpoint = "unix:///var/run/docker.sock"
|
||||
#domain = "localhost"
|
||||
#watch = true
|
||||
## This will hide all docker containers that don't have explicitly
|
||||
## set label to "enable"
|
||||
#exposedbydefault = false
|
||||
Reference in New Issue
Block a user