mirror of
https://gitlab.com/cyber5k/mistborn.git
synced 2022-06-09 18:03:35 +03:00
Docker
This commit is contained in:
10
LICENSE
Normal file
10
LICENSE
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2019, Steven Foerster
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
172
base.yml
Normal file
172
base.yml
Normal file
@@ -0,0 +1,172 @@
|
||||
version: '3'
|
||||
|
||||
volumes:
|
||||
production_postgres_data: {}
|
||||
production_postgres_data_backups: {}
|
||||
production_traefik: {}
|
||||
|
||||
services:
|
||||
django: &django
|
||||
image: cyber5k/mistborn:latest
|
||||
container_name: mistborn_production_django
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=5000"
|
||||
env_file:
|
||||
- ./.envs/.production/.django
|
||||
- ./.envs/.production/.postgres
|
||||
volumes:
|
||||
- /home/mistborn/.ssh:/ssh
|
||||
- ../mistborn_volumes/base/media:/mistborn-media
|
||||
- ../mistborn_volumes/base/private_media:/mistborn-private-media
|
||||
command: /start
|
||||
|
||||
postgres:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/production/postgres/Dockerfile
|
||||
image: mistborn_production_postgres
|
||||
container_name: mistborn_production_postgres
|
||||
volumes:
|
||||
- production_postgres_data:/var/lib/postgresql/data
|
||||
- production_postgres_data_backups:/backups
|
||||
env_file:
|
||||
- ./.envs/.production/.postgres
|
||||
|
||||
traefik:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/production/traefik/Dockerfile
|
||||
image: mistborn_production_traefik
|
||||
container_name: mistborn_production_traefik
|
||||
depends_on:
|
||||
- django
|
||||
volumes:
|
||||
- production_traefik:/etc/traefik/acme
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- "0.0.0.0:80:80/tcp"
|
||||
|
||||
redis:
|
||||
image: redis:5.0
|
||||
container_name: mistborn_production_redis
|
||||
|
||||
celeryworker:
|
||||
image: cyber5k/mistborn:latest
|
||||
container_name: mistborn_production_celeryworker
|
||||
volumes:
|
||||
- /home/mistborn/.ssh:/ssh
|
||||
- ../mistborn_volumes/base/media:/mistborn-media
|
||||
- ../mistborn_volumes/base/private_media:/mistborn-private-media
|
||||
env_file:
|
||||
- ./.envs/.production/.django
|
||||
- ./.envs/.production/.postgres
|
||||
- ./.envs/.production/.pihole
|
||||
networks:
|
||||
default:
|
||||
dns_net:
|
||||
ipv4_address: 10.2.1.3
|
||||
dns:
|
||||
- 10.2.1.2
|
||||
depends_on:
|
||||
- traefik
|
||||
- pihole
|
||||
command: /start-celeryworker
|
||||
|
||||
celeryworker-low-priority:
|
||||
image: cyber5k/mistborn:latest
|
||||
container_name: mistborn_production_celeryworker_low_priority
|
||||
volumes:
|
||||
- /home/mistborn/.ssh:/ssh
|
||||
- ../mistborn_volumes/base/media:/mistborn-media
|
||||
- ../mistborn_volumes/base/private_media:/mistborn-private-media
|
||||
env_file:
|
||||
- ./.envs/.production/.django
|
||||
- ./.envs/.production/.postgres
|
||||
- ./.envs/.production/.pihole
|
||||
networks:
|
||||
default:
|
||||
dns_net:
|
||||
ipv4_address: 10.2.1.4
|
||||
dns:
|
||||
- 10.2.1.2
|
||||
depends_on:
|
||||
- traefik
|
||||
- pihole
|
||||
command: /start-celeryworker-low-priority
|
||||
|
||||
celerybeat:
|
||||
image: cyber5k/mistborn:latest
|
||||
container_name: mistborn_production_celerybeat
|
||||
env_file:
|
||||
- ./.envs/.production/.django
|
||||
- ./.envs/.production/.postgres
|
||||
command: /start-celerybeat
|
||||
|
||||
|
||||
flower:
|
||||
image: cyber5k/mistborn:latest
|
||||
container_name: mistborn_production_flower
|
||||
ports:
|
||||
- "5555:5555/tcp"
|
||||
command: /start-flower
|
||||
|
||||
pihole:
|
||||
container_name: mistborn_production_pihole
|
||||
image: pihole/pihole:latest
|
||||
ports:
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
environment:
|
||||
- ServerIP=10.2.0.3
|
||||
- DNS1='10.2.0.2#5054' # docs say port 5054, was 54; use network_mode: host to see which port is used
|
||||
- DNS2=''
|
||||
- IPv6='false'
|
||||
- DNSMASQ_LISTENING=all
|
||||
# TZ: 'America/New York'
|
||||
# Volumes store your data between container upgrades
|
||||
env_file:
|
||||
- ./.envs/.production/.pihole
|
||||
volumes:
|
||||
- ../mistborn_volumes/base/pihole/etc-pihole:/etc/pihole/
|
||||
- ../mistborn_volumes/base/pihole/etc-dnsmasqd:/etc/dnsmasq.d/
|
||||
dns:
|
||||
- 127.0.0.1
|
||||
networks:
|
||||
default:
|
||||
pihole_net:
|
||||
ipv4_address: 10.2.0.3
|
||||
dns_net:
|
||||
ipv4_address: 10.2.1.2
|
||||
restart: unless-stopped
|
||||
|
||||
dnscrypt-proxy:
|
||||
container_name: mistborn_production_dnscrypt_proxy
|
||||
image: djaydev/dnscrypt-proxy
|
||||
environment:
|
||||
- DNSCRYPT_LISTEN_PORT=5054
|
||||
# resolvers: https://download.dnscrypt.info/dnscrypt-resolvers/v2/public-resolvers.md
|
||||
#- DNSCRYPT_SERVER_NAMES=['scaleway-fr','google','yandex','cloudflare']
|
||||
- DNSCRYPT_SERVER_NAMES=['cloudflare','dnswarden-doh1','dnswarden-doh2','dnswarden-doh3','securedns-doh','adguard-dns-doh']
|
||||
networks:
|
||||
pihole_net:
|
||||
ipv4_address: 10.2.0.2
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
networks:
|
||||
pihole_net:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.2.0.0/29
|
||||
dns_net:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.2.1.0/24
|
||||
6
compose/production/postgres/Dockerfile
Normal file
6
compose/production/postgres/Dockerfile
Normal file
@@ -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
|
||||
}
|
||||
41
compose/production/postgres/maintenance/_sourced/messages.sh
Normal file
41
compose/production/postgres/maintenance/_sourced/messages.sh
Normal file
@@ -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: ${@}"
|
||||
}
|
||||
16
compose/production/postgres/maintenance/_sourced/yes_no.sh
Normal file
16
compose/production/postgres/maintenance/_sourced/yes_no.sh
Normal file
@@ -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
|
||||
}
|
||||
38
compose/production/postgres/maintenance/backup
Normal file
38
compose/production/postgres/maintenance/backup
Normal file
@@ -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}'."
|
||||
22
compose/production/postgres/maintenance/backups
Normal file
22
compose/production/postgres/maintenance/backups
Normal file
@@ -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}"
|
||||
55
compose/production/postgres/maintenance/restore
Normal file
55
compose/production/postgres/maintenance/restore
Normal file
@@ -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."
|
||||
13
compose/production/tor/Dockerfile
Normal file
13
compose/production/tor/Dockerfile
Normal file
@@ -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
|
||||
25
compose/production/tor/torrc
Normal file
25
compose/production/tor/torrc
Normal file
@@ -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
|
||||
5
compose/production/traefik/Dockerfile
Normal file
5
compose/production/traefik/Dockerfile
Normal file
@@ -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
|
||||
176
compose/production/traefik/traefik.toml
Normal file
176
compose/production/traefik/traefik.toml
Normal file
@@ -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
|
||||
24
extra/bitwarden.yml
Normal file
24
extra/bitwarden.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
version: '3'
|
||||
|
||||
#volumes:
|
||||
# production_bitwarden_data: {}
|
||||
|
||||
services:
|
||||
bitwarden:
|
||||
image: bitwardenrs/server:latest
|
||||
container_name: mistborn_production_bitwarden
|
||||
env_file:
|
||||
- ../.envs/.production/.bitwarden
|
||||
volumes:
|
||||
- ../../mistborn_volumes/extra/bitwarden:/data
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=80"
|
||||
ports:
|
||||
- 3012:3012/tcp
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
20
extra/homeassistant.yml
Normal file
20
extra/homeassistant.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
homeassistant:
|
||||
container_name: mistborn_production_home_assistant
|
||||
image: homeassistant/home-assistant:stable
|
||||
volumes:
|
||||
- ../../mistborn_volumes/extra/homeassistant/config:/config
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=8123"
|
||||
restart: unless-stopped
|
||||
#network_mode: host
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
24
extra/jellyfin.yml
Normal file
24
extra/jellyfin.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
version: '3'
|
||||
|
||||
volumes:
|
||||
production_jellyfin_config: {}
|
||||
production_jellyfin_cache: {}
|
||||
#production_nextcloud: {}
|
||||
|
||||
services:
|
||||
jellyfin:
|
||||
image: jellyfin/jellyfin:latest
|
||||
container_name: mistborn_production_jellyfin
|
||||
volumes:
|
||||
- production_jellyfin_config:/config
|
||||
- production_jellyfin_cache:/cache
|
||||
- ../../mistborn_volumes/extra/nextcloud:/media:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=8096"
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
29
extra/nextcloud.yml
Normal file
29
extra/nextcloud.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
version: '3'
|
||||
|
||||
#volumes:
|
||||
# production_nextcloud: {}
|
||||
|
||||
services:
|
||||
nextcloud:
|
||||
image: nextcloud
|
||||
container_name: mistborn_production_nextcloud
|
||||
env_file:
|
||||
- ../.envs/.production/.postgres
|
||||
- ../.envs/.production/.nextcloud
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=80"
|
||||
volumes:
|
||||
- ../../mistborn_volumes/extra/nextcloud:/var/www/html
|
||||
#- ./volumes/extra/nextcloud/config:/var/www/html/config
|
||||
#- ./volumes/extra/nextcloud/custom_apps:/var/www/html/custom_apps
|
||||
#- ./volumes/extra/nextcloud/data:/var/www/html/data
|
||||
#- ./volumes/extra/nextcloud/themes:/var/www/html/themes
|
||||
environment:
|
||||
- VIRTUAL_HOST=nextcloud.mistborn
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
21
extra/onlyoffice.yml
Normal file
21
extra/onlyoffice.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
onlyoffice:
|
||||
container_name: mistborn_production_onlyoffice
|
||||
image: onlyoffice/documentserver:latest
|
||||
volumes:
|
||||
- ../../mistborn_volumes/extra/onlyoffice/logs:/var/log/onlyoffice
|
||||
- ../../mistborn_volumes/extra/onlyoffice/cache:/var/lib/onlyoffice
|
||||
env_file:
|
||||
- ../.envs/.production/.onlyoffice
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=80"
|
||||
restart: unless-stopped
|
||||
#network_mode: host
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
25
extra/raspap.yml
Normal file
25
extra/raspap.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
raspap:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ./compose/production/raspap/Dockerfile
|
||||
#user: root
|
||||
image: mistborn_production_raspap
|
||||
container_name: mistborn_production_raspap
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=80"
|
||||
env_file:
|
||||
- ../.envs/.production/.pihole
|
||||
command: /start
|
||||
volumes:
|
||||
#- ~/.ssh:/ssh:ro
|
||||
- ../../mistborn_volumes/extra/raspap/etc-raspap:/etc/raspap
|
||||
#- ../volumes/extra/raspap/etc-lighttpd:/etc/lighttpd
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
65
extra/rocketchat.yml
Normal file
65
extra/rocketchat.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
# rocketchat
|
||||
rocketchat:
|
||||
image: rocket.chat:latest
|
||||
container_name: mistborn_production_rocketchat
|
||||
command: bash -c 'for i in `seq 1 30`; do node main.js && s=$$? && break || s=$$?; echo "Tried $$i times. Waiting 5 secs..."; sleep 5; done; (exit $$s)'
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ../../mistborn_volumes/extra/rocketchat/uploads:/app/uploads
|
||||
environment:
|
||||
- PORT=3000
|
||||
- ROOT_URL=http://chat.mistborn
|
||||
- MONGO_URL=mongodb://mongo:27017/rocketchat
|
||||
- MONGO_OPLOG_URL=mongodb://mongo:27017/local
|
||||
- Accounts_UseDNSDomainCheck=False
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=3000"
|
||||
depends_on:
|
||||
- mongo
|
||||
#ports:
|
||||
# - 3000:3000
|
||||
|
||||
mongo:
|
||||
image: mongo:4.0
|
||||
container_name: mistborn_production_rocketchat_mongo
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ../volumes/extra/rocketchat/data/db:/data/db
|
||||
- ../volumes/extra/rocketchat/data/dump:/dump
|
||||
command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1
|
||||
|
||||
# this container's job is just run the command to initialize the replica set.
|
||||
# it will run the command and remove himself (it will not stay running)
|
||||
mongo-init-replica:
|
||||
image: mongo
|
||||
command: 'bash -c "for i in `seq 1 30`; do mongo mongo/rocketchat --eval \"rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017'' } ]})\" && s=$$? && break || s=$$?; echo \"Tried $$i times. Waiting 5 secs...\"; sleep 5; done; (exit $$s)"'
|
||||
depends_on:
|
||||
- mongo
|
||||
|
||||
# hubot, the popular chatbot (add the bot user first and change the password before starting this image)
|
||||
hubot:
|
||||
image: rocketchat/hubot-rocketchat:latest
|
||||
container_name: mistborn_production_rocketchat_hubot
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- ROCKETCHAT_URL=chat.mistborn #:3000
|
||||
# you can add more scripts as you'd like here, they need to be installable by npm
|
||||
- EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics
|
||||
env_file:
|
||||
- ../.envs/.production/.rocketchat
|
||||
depends_on:
|
||||
- rocketchat
|
||||
volumes:
|
||||
- ../volumes/extra/rocketchat/hubot/scripts:/home/hubot/scripts
|
||||
# this is used to expose the hubot port for notifications on the host on port 3001, e.g. for hubot-jenkins-notifier
|
||||
ports:
|
||||
- 3001:8080/tcp
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
28
extra/syncthing.yml
Normal file
28
extra/syncthing.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
syncthing:
|
||||
image: linuxserver/syncthing
|
||||
container_name: mistborn_production_syncthing
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Amereica/New_York
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- ../../mistborn_volumes/extra/syncthing/config:/config
|
||||
- ../../mistborn_volumes/extra/syncthing/data1:/data1
|
||||
- ../../mistborn_volumes/extra/syncthing/data2:/data2
|
||||
ports:
|
||||
#- 8384:8384
|
||||
- 22000:22000/tcp # listening port
|
||||
- 21027:21027/udp # protocol discovery
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.port=8384"
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
16
extra/tor.yml
Normal file
16
extra/tor.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
tor-client:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ./compose/production/tor/Dockerfile
|
||||
image: mistborn_production_tor
|
||||
container_name: mistborn_production_tor
|
||||
ports:
|
||||
- 9150:9150/tcp
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mistborn_default
|
||||
8
scripts/conf/15-iptables.conf
Normal file
8
scripts/conf/15-iptables.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
# Log kernel iptables dropped messages to iptables.log
|
||||
$template MyTemplate,"%$day%-%timegenerated:1:3:date-rfc3164%-%$year% %timegenerated:12:19:date-rfc3339% %HOSTNAME% %syslogtag% %msg%\n"
|
||||
:msg,contains,"[IPTables-Dropped]:" /var/log/iptables.log;MyTemplate #RSYSLOG_FileFormat
|
||||
|
||||
# Uncomment the following to stop logging anything that matches the last rule.
|
||||
# Doing this will stop logging kernel generated UFW log messages to the file
|
||||
# normally containing kern.* messages (eg, /var/log/kern.log)
|
||||
#& stop
|
||||
2
scripts/conf/20auto-upgrades
Normal file
2
scripts/conf/20auto-upgrades
Normal file
@@ -0,0 +1,2 @@
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
36
scripts/conf/50unattended-upgrades
Normal file
36
scripts/conf/50unattended-upgrades
Normal file
@@ -0,0 +1,36 @@
|
||||
// Automatically upgrade packages from these (origin, archive) pairs
|
||||
Unattended-Upgrade::Allowed-Origins {
|
||||
// ${distro_id} and ${distro_codename} will be automatically expanded
|
||||
"${distro_id} stable";
|
||||
"${distro_id} ${distro_codename}-security";
|
||||
|
||||
// Autoupdate Nginx
|
||||
"nginx:${distro_codename}";
|
||||
|
||||
// Autoupdate WireGuard
|
||||
"LP-PPA-wireguard-wireguard:${distro_codename}";
|
||||
};
|
||||
|
||||
// List of packages to not update
|
||||
Unattended-Upgrade::Package-Blacklist {
|
||||
};
|
||||
|
||||
// Do automatic removal of new unused dependencies after the upgrade
|
||||
// (equivalent to apt-get autoremove)
|
||||
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
||||
|
||||
// Automatically reboot *WITHOUT CONFIRMATION* if a
|
||||
// the file /var/run/reboot-required is found after the upgrade
|
||||
Unattended-Upgrade::Automatic-Reboot "true";
|
||||
|
||||
// If automatic reboot is enabled and needed, reboot at the specific
|
||||
// time instead of immediately
|
||||
// Default: "now"
|
||||
Unattended-Upgrade::Automatic-Reboot-Time "00:00";
|
||||
|
||||
// Avoid conffile dpkg prompt by *always* leaving the modified configuration in
|
||||
// place and putting the new package configuration in a .dpkg-dist file
|
||||
Dpkg::Options {
|
||||
"--force-confdef";
|
||||
"--force-confold";
|
||||
};
|
||||
3
scripts/conf/cockpit.conf
Normal file
3
scripts/conf/cockpit.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
[WebService]
|
||||
ProtocolHeader = X-Forwarded-Proto
|
||||
AllowUnencrypted=true
|
||||
238
scripts/install.sh
Executable file
238
scripts/install.sh
Executable file
@@ -0,0 +1,238 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
## ensure run as nonroot user
|
||||
#if [ "$EUID" -eq 0 ]; then
|
||||
MISTBORN_USER="mistborn"
|
||||
if [ $(whoami) != "$MISTBORN_USER" ]; then
|
||||
echo "Creating user: $MISTBORN_USER"
|
||||
sudo useradd -s /bin/bash -d /home/$MISTBORN_USER -m -G sudo $MISTBORN_USER 2>/dev/null || true
|
||||
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
|
||||
#echo "SCRIPTPATH: $SCRIPTPATH"
|
||||
FILENAME=$(basename -- "$0")
|
||||
#echo "FILENAME: $FILENAME"
|
||||
FULLPATH="$SCRIPTPATH/$FILENAME"
|
||||
#echo "FULLPATH: $FULLPATH"
|
||||
|
||||
# SUDO
|
||||
case `sudo grep -e "^$MISTBORN_USER.*" /etc/sudoers >/dev/null; echo $?` in
|
||||
0)
|
||||
echo "$MISTBORN_USER already in sudoers"
|
||||
;;
|
||||
1)
|
||||
echo "Adding $MISTBORN_USER to sudoers"
|
||||
sudo bash -c "echo '$MISTBORN_USER ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"
|
||||
;;
|
||||
*)
|
||||
echo "There was a problem checking sudoers"
|
||||
;;
|
||||
esac
|
||||
|
||||
# get git branch if one exists (default to master)
|
||||
pushd .
|
||||
cd $SCRIPTPATH
|
||||
GIT_BRANCH=$(git symbolic-ref --short HEAD || echo "master")
|
||||
popd
|
||||
|
||||
sudo cp $FULLPATH /home/$MISTBORN_USER
|
||||
sudo chown $MISTBORN_USER:$MISTBORN_USER /home/$MISTBORN_USER/$FILENAME
|
||||
sudo SSH_CLIENT="$SSH_CLIENT" MISTBORN_DEFAULT_PASSWORD="$MISTBORN_DEFAULT_PASSWORD" GIT_BRANCH="$GIT_BRANCH" -i -u $MISTBORN_USER bash -c "/home/$MISTBORN_USER/$FILENAME" # self-referential call
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Running as $USER"
|
||||
|
||||
# banner
|
||||
echo -e " ____ _ ____ _ __"
|
||||
echo -e " / ___| _| |__ ___ _ __ | ___|| |/ /"
|
||||
echo -e "| | | | | | '_ \ / _ \ '__| |___ \| ' /"
|
||||
echo -e "| |__| |_| | |_) | __/ | ___) | . \ "
|
||||
echo -e " \____\__, |_.__/ \___|_| |____/|_|\_\ "
|
||||
echo -e " |___/"
|
||||
echo -e " __ __ _ _ _"
|
||||
echo -e "| \/ (_)___| |_| |__ ___ _ __ _ __"
|
||||
echo -e "| |\/| | / __| __| '_ \ / _ \| '__| '_ \ "
|
||||
echo -e "| | | | \__ \ |_| |_) | (_) | | | | | |"
|
||||
echo -e "|_| |_|_|___/\__|_.__/ \___/|_| |_| |_|"
|
||||
echo -e ""
|
||||
|
||||
# Get OS info
|
||||
# Determine OS platform
|
||||
UNAME=$(uname | tr "[:upper:]" "[:lower:]")
|
||||
DISTRO=""
|
||||
# If Linux, try to determine specific distribution
|
||||
if [ "$UNAME" == "linux" ]; then
|
||||
# use /etc/os-release to get distro
|
||||
DISTRO=$(cat /etc/os-release | awk -F= '/^ID=/{print $2}')
|
||||
fi
|
||||
|
||||
echo "UNAME: $UNAME"
|
||||
echo "DISTRO: $DISTRO"
|
||||
|
||||
# INPUT default admin password
|
||||
if [ -z "${MISTBORN_DEFAULT_PASSWORD}" ]; then
|
||||
read -p "(Mistborn) Set default admin password: " -s MISTBORN_DEFAULT_PASSWORD
|
||||
echo
|
||||
else
|
||||
echo "MISTBORN_DEFAULT_PASSWORD is already set"
|
||||
fi
|
||||
|
||||
# SSH keys
|
||||
if [ ! -f ~/.ssh/id_rsa ]; then
|
||||
echo "Generating SSH keypair for $USER"
|
||||
ssh-keygen -t rsa -b 4096 -N "" -m pem -f ~/.ssh/id_rsa -q
|
||||
|
||||
# Authorized keys
|
||||
echo "from=\"172.16.0.0/12,192.168.0.0/16,10.0.0.0/8\" $(cat ~/.ssh/id_rsa.pub)" > ~/.ssh/authorized_keys
|
||||
else
|
||||
echo "SSH key exists for $USER"
|
||||
fi
|
||||
|
||||
sudo rm -rf /opt/mistborn 2>/dev/null || true
|
||||
|
||||
# clone to /opt and change directory
|
||||
echo "Cloning $GIT_BRANCH branch from mistborn repo"
|
||||
sudo git clone https://gitlab.com/cyber5k/mistborn.git -b $GIT_BRANCH /opt/mistborn
|
||||
sudo chown -R $USER:$USER /opt/mistborn
|
||||
pushd .
|
||||
cd /opt/mistborn
|
||||
git submodule update --init --recursive
|
||||
|
||||
# iptables
|
||||
echo "Setting up firewall (iptables)"
|
||||
if [ ! -f "/etc/iptables/rules.v4" ]; then
|
||||
echo "Setting iptables rules..."
|
||||
./scripts/subinstallers/iptables.sh
|
||||
else
|
||||
echo "iptables rules exist. Leaving alone."
|
||||
fi
|
||||
|
||||
|
||||
# SSH Server
|
||||
sudo apt-get install -y openssh-server
|
||||
sudo sed -i 's/#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
|
||||
sudo sed -i 's/PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
|
||||
sudo sed -i 's/#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
|
||||
sudo sed -i 's/PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
|
||||
sudo systemctl restart ssh
|
||||
|
||||
# Additional tools fail2ban
|
||||
sudo apt-get install -y dnsutils fail2ban
|
||||
|
||||
# Install kernel headers
|
||||
if [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ]; then
|
||||
sudo apt install -y linux-headers-$(uname -r)
|
||||
elif [ "$DISTRO" == "raspbian" ]; then
|
||||
sudo apt-get install -y raspberrypi-kernel-headers
|
||||
fi
|
||||
|
||||
# Wireugard
|
||||
source ./scripts/subinstallers/wireguard.sh
|
||||
|
||||
# Docker
|
||||
source ./scripts/subinstallers/docker.sh
|
||||
|
||||
# Unattended upgrades
|
||||
sudo apt-get install -y unattended-upgrades
|
||||
|
||||
# Cockpit
|
||||
source ./scripts/subinstallers/cockpit.sh
|
||||
|
||||
# Mistborn
|
||||
# final setup vars
|
||||
iface=$(ip -o -4 route show to default | egrep -o 'dev [^ ]*' | awk '{print $2}')
|
||||
IPV4_PUBLIC=$(ip -o -4 route show default | egrep -o 'dev [^ ]*' | awk '{print $2}' | xargs ip -4 addr show | grep 'inet ' | awk '{print $2}' | grep -o "^[0-9.]*" | tr -cd '\11\12\15\40-\176' | head -1) # tail -1 to get last
|
||||
|
||||
# clean
|
||||
if [ -f "/etc/systemd/system/Mistborn-base.service" ]; then
|
||||
sudo systemctl stop Mistborn*.service 2>/dev/null || true
|
||||
sudo systemctl disable Mistborn*.service 2>/dev/null || true
|
||||
fi
|
||||
|
||||
sudo docker volume rm -f mistborn_production_postgres_data 2>/dev/null || true
|
||||
sudo docker volume rm -f mistborn_production_postgres_data_backups 2>/dev/null || true
|
||||
sudo docker volume rm -f mistborn_production_traefik 2>/dev/null || true
|
||||
|
||||
# generate production .env file
|
||||
if [ ! -d ./.envs/.production ]; then
|
||||
./scripts/subinstallers/gen_prod_env.sh "$MISTBORN_DEFAULT_PASSWORD"
|
||||
fi
|
||||
|
||||
# unattended upgrades
|
||||
sudo cp ./scripts/conf/20auto-upgrades /etc/apt/apt.conf.d/
|
||||
sudo cp ./scripts/conf/50unattended-upgrades /etc/apt/apt.conf.d/
|
||||
|
||||
sudo systemctl stop unattended-upgrades
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart unattended-upgrades
|
||||
|
||||
# setup Mistborn services
|
||||
|
||||
# install and start base services
|
||||
# default interface
|
||||
sudo cp ./scripts/services/Mistborn* /etc/systemd/system/
|
||||
sudo find /etc/systemd/system/ -type f -name 'Mistborn*' | xargs sudo sed -i "s/User=.*/User=$USER/"
|
||||
sudo find /etc/systemd/system/ -type f -name 'Mistborn*' | xargs sudo sed -i "s/ root:root / $USER:$USER /"
|
||||
sudo find /etc/systemd/system/ -type f -name 'Mistborn*' | xargs sudo sed -i "s/DIFACE/$iface/"
|
||||
|
||||
if [ "$DISTRO" == "debian" ] || [ "$DISTRO" == "raspbian" ]; then
|
||||
# remove systemd-resolved lines
|
||||
sudo sed -i '/.*systemd-resolved/d' /etc/systemd/system/Mistborn-base.service
|
||||
fi
|
||||
|
||||
# setup local volumes for pihole
|
||||
sudo mkdir -p ../mistborn_volumes/
|
||||
sudo chown -R root:root ../mistborn_volumes/
|
||||
sudo mkdir -p ../mistborn_volumes/base/pihole/etc-pihole
|
||||
sudo mkdir -p ../mistborn_volumes/base/pihole/etc-dnsmasqd
|
||||
echo "addn-hosts=/etc/pihole/lan.list" | sudo tee ../mistborn_volumes/base/pihole/etc-dnsmasqd/02-lan.conf
|
||||
sudo touch ../mistborn_volumes/base/pihole/etc-pihole/lan.list
|
||||
sudo mkdir -p ../mistborn_volumes/extra
|
||||
|
||||
# Traefik final setup (cockpit)
|
||||
sudo sed -i "s/IPV4_PUBLIC/$IPV4_PUBLIC/" ./compose/production/traefik/traefik.toml
|
||||
|
||||
# Download docker images while DNS is operable
|
||||
sudo docker-compose -f base.yml pull || true
|
||||
sudo docker-compose -f base.yml build
|
||||
|
||||
# DNS
|
||||
sudo systemctl stop systemd-resolved 2>/dev/null || true
|
||||
sudo systemctl disable systemd-resolved 2>/dev/null || true
|
||||
|
||||
# array of dns entries to add (not not already present)
|
||||
declare -a dnslist=("pihole.mistborn" \
|
||||
"home.mistborn" \
|
||||
"hass.mistborn" \
|
||||
"syncthing.mistborn" \
|
||||
"chat.mistborn" \
|
||||
"tor.mistborn" \
|
||||
"nextcloud.mistborn" \
|
||||
"onlyoffice.mistborn" \
|
||||
"bitwarden.mistborn" \
|
||||
"jellyfin.mistborn" \
|
||||
"raspap.mistborn" \
|
||||
"cockpit.mistborn")
|
||||
|
||||
for dnsname in "${dnslist[@]}"
|
||||
do
|
||||
sudo grep -qF "$dnsname" ../mistborn_volumes/base/pihole/etc-pihole/lan.list \
|
||||
&& echo "$dnsname already in DNS" \
|
||||
|| echo "$IPV4_PUBLIC $dnsname" | sudo tee -a ../mistborn_volumes/base/pihole/etc-pihole/lan.list
|
||||
done
|
||||
|
||||
# ResolvConf (OpenResolv installed with Wireguard)
|
||||
sudo sed -i "s/#name_servers.*/name_servers=$IPV4_PUBLIC/" /etc/resolvconf.conf
|
||||
sudo sed -i "s/name_servers.*/name_servers=$IPV4_PUBLIC/" /etc/resolvconf.conf
|
||||
#sudo sed -i "s/#name_servers.*/name_servers=127.0.0.1/" /etc/resolvconf.conf
|
||||
sudo resolvconf -u 1>/dev/null 2>&1
|
||||
|
||||
echo "backup up original volumes folder"
|
||||
sudo mkdir -p ../mistborn_backup
|
||||
sudo tar -czf ../mistborn_backup/mistborn_volumes_backup.tar.gz ../mistborn_volumes 1>/dev/null 2>&1
|
||||
|
||||
# start base service
|
||||
sudo systemctl enable Mistborn-base.service
|
||||
sudo systemctl start Mistborn-base.service
|
||||
popd
|
||||
37
scripts/services/Mistborn-base.service
Normal file
37
scripts/services/Mistborn-base.service
Normal file
@@ -0,0 +1,37 @@
|
||||
[Unit]
|
||||
Description=Mistborn Base
|
||||
Requires=docker.service
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml down
|
||||
ExecStartPre=/bin/chown -R root:root /opt/mistborn_volumes/
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml build
|
||||
ExecStartPre=/bin/systemctl stop systemd-resolved
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 80 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 5555 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/iptables -A OUTPUT -o DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/ip6tables -A OUTPUT -p udp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/resolvconf -u
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml up
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml down
|
||||
# Post stop
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 80 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 5555 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/sbin/iptables -D OUTPUT -o DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/sbin/ip6tables -D OUTPUT -p udp --dport 53 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/bin/systemctl start systemd-resolved
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
scripts/services/Mistborn-bitwarden.service
Normal file
23
scripts/services/Mistborn-bitwarden.service
Normal file
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=Mistborn Bitwarden Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 3012 -j MISTBORN_LOG_DROP
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml down
|
||||
# Post stop
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 3012 -j MISTBORN_LOG_DROP
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
21
scripts/services/Mistborn-homeassistant.service
Normal file
21
scripts/services/Mistborn-homeassistant.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Mistborn Home Assistant
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/homeassistant.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/homeassistant.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/homeassistant.yml down
|
||||
# Post stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
21
scripts/services/Mistborn-jellyfin.service
Normal file
21
scripts/services/Mistborn-jellyfin.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Mistborn Jellyfin Service
|
||||
Requires=Mistborn-nextcloud.service
|
||||
After=Mistborn-nextcloud.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jellyfin.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jellyfin.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jellyfin.yml down
|
||||
# Post stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
21
scripts/services/Mistborn-nextcloud.service
Normal file
21
scripts/services/Mistborn-nextcloud.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Mistborn Nextcloud Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/nextcloud.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/nextcloud.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/nextcloud.yml down
|
||||
# Post stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
21
scripts/services/Mistborn-onlyoffice.service
Normal file
21
scripts/services/Mistborn-onlyoffice.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Mistborn OnlyOffice Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/onlyoffice.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/onlyoffice.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/onlyoffice.yml down
|
||||
# Post stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
21
scripts/services/Mistborn-raspap.service
Normal file
21
scripts/services/Mistborn-raspap.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Mistborn RaspAP Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/raspap.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/raspap.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/raspap.yml down
|
||||
# Post stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
scripts/services/Mistborn-rocketchat.service
Normal file
23
scripts/services/Mistborn-rocketchat.service
Normal file
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=Mistborn Rocket Chat Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 3001 -j MISTBORN_LOG_DROP
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml down
|
||||
# Post stop
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 3001 -j MISTBORN_LOG_DROP
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
25
scripts/services/Mistborn-syncthing.service
Normal file
25
scripts/services/Mistborn-syncthing.service
Normal file
@@ -0,0 +1,25 @@
|
||||
[Unit]
|
||||
Description=Mistborn Syncthing Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p udp --dport 21027 -j MISTBORN_LOG_DROP
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 22000 -j MISTBORN_LOG_DROP
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml down
|
||||
# Post stop
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p udp --dport 21027 -j MISTBORN_LOG_DROP
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 22000 -j MISTBORN_LOG_DROP
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
scripts/services/Mistborn-tor.service
Normal file
23
scripts/services/Mistborn-tor.service
Normal file
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=Mistborn Tor Service
|
||||
Requires=Mistborn-base.service
|
||||
After=Mistborn-base.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
User=root
|
||||
Group=docker
|
||||
PermissionsStartOnly=true
|
||||
# Shutdown container (if running) when unit is stopped
|
||||
ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml down
|
||||
ExecStartPre=/bin/chown -R --from=root:root root:root /opt/mistborn_volumes/
|
||||
ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 9150 -j MISTBORN_LOG_DROP
|
||||
# Start container when unit is started
|
||||
ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml up --build
|
||||
# Stop container when unit is stopped
|
||||
ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml down
|
||||
# Post stop
|
||||
ExecStopPost=/sbin/iptables -D DOCKER-USER -i DIFACE -p tcp --dport 9150 -j MISTBORN_LOG_DROP
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
4
scripts/services/raspap/install.sh
Executable file
4
scripts/services/raspap/install.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# install on gateway
|
||||
sudo apt-get install -y hostapd vnstat
|
||||
29
scripts/subinstallers/cockpit.sh
Executable file
29
scripts/subinstallers/cockpit.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Cockpit
|
||||
echo "Installing Cockpit"
|
||||
if [ "$DISTRO" == "ubuntu" ]; then
|
||||
echo "Ubuntu backports enabled by default"
|
||||
|
||||
sudo apt-get install -y cockpit cockpit-docker
|
||||
|
||||
elif [ "$DISTRO" == "debian" ]; then
|
||||
sudo grep -qF "buster-backports" /etc/apt/sources.list.d/backports.list \
|
||||
&& echo "buster-backports already in sources" \
|
||||
|| echo 'deb http://deb.debian.org/debian buster-backports main' | sudo tee -a /etc/apt/sources.list.d/backports.list
|
||||
|
||||
sudo apt-get install -y cockpit cockpit-docker
|
||||
|
||||
elif [ "$DISTRO" == "raspbian" ]; then
|
||||
|
||||
echo "Raspbian repos contain cockpit"
|
||||
sudo apt-get install -y cockpit cockpit-docker
|
||||
|
||||
fi
|
||||
|
||||
sudo cp ./scripts/conf/cockpit.conf /etc/cockpit/cockpit.conf
|
||||
sudo systemctl restart cockpit.socket
|
||||
|
||||
# create system cockpit user
|
||||
echo "Creating cockpit user"
|
||||
sudo useradd -s /bin/bash -d /home/cockpit -m -G sudo -p $(openssl passwd -1 "$MISTBORN_DEFAULT_PASSWORD") cockpit || true
|
||||
70
scripts/subinstallers/docker.sh
Executable file
70
scripts/subinstallers/docker.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Docker
|
||||
# dependencies
|
||||
echo "Installing Docker dependencies"
|
||||
sudo apt-get install -y \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg-agent \
|
||||
software-properties-common
|
||||
|
||||
# Docker repo key
|
||||
echo "Adding docker repository key"
|
||||
if [ "$DISTRO" == "ubuntu" ]; then
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||
elif [ "$DISTRO" == "debian" ]; then
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
|
||||
elif [ "$DISTRO" == "raspbian" ]; then
|
||||
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -
|
||||
fi
|
||||
|
||||
# Docker repo to source list
|
||||
echo "Adding docker to sources list"
|
||||
if [ "$DISTRO" == "ubuntu" ]; then
|
||||
sudo add-apt-repository -y \
|
||||
"deb https://download.docker.com/linux/ubuntu \
|
||||
$(lsb_release -cs) \
|
||||
stable"
|
||||
elif [ "$DISTRO" == "debian" ]; then
|
||||
sudo add-apt-repository -y \
|
||||
"deb https://download.docker.com/linux/debian \
|
||||
$(lsb_release -cs) \
|
||||
stable"
|
||||
elif [ "$DISTRO" == "raspbian" ]; then
|
||||
echo "deb [arch=armhf] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
|
||||
$(lsb_release -cs) stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list
|
||||
fi
|
||||
|
||||
# install Docker
|
||||
echo "Installing docker"
|
||||
sudo apt-get update
|
||||
|
||||
if [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ]; then
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
||||
elif [ "$DISTRO" == "raspbian" ]; then
|
||||
sudo apt install -y --no-install-recommends \
|
||||
docker-ce \
|
||||
cgroupfs-mount
|
||||
fi
|
||||
|
||||
# Docker group
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
# Docker Compose
|
||||
echo "Installing Docker Compose"
|
||||
#if [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ]; then
|
||||
# sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
# sudo chmod +x /usr/local/bin/docker-compose
|
||||
#elif [ "$DISTRO" == "raspbian" ]; then
|
||||
# Install required packages
|
||||
sudo apt update
|
||||
sudo apt install -y python python3-pip libffi-dev python-backports.ssl-match-hostname
|
||||
|
||||
# Install Docker Compose from pip
|
||||
# This might take a while
|
||||
sudo pip3 install docker-compose
|
||||
#fi
|
||||
|
||||
64
scripts/subinstallers/gen_prod_env.sh
Executable file
64
scripts/subinstallers/gen_prod_env.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
|
||||
# generate production .env file for Django
|
||||
mkdir -p ./.envs/.production
|
||||
DJANGO_PROD_FILE="./.envs/.production/.django"
|
||||
DJANGO_SECRET_KEY=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(50)]))")
|
||||
#CELERY_FLOWER_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")
|
||||
MISTBORN_DEFAULT_PASSWORD="$1"
|
||||
echo "DJANGO_SETTINGS_MODULE=config.settings.production" > $DJANGO_PROD_FILE
|
||||
echo "DJANGO_SECRET_KEY=$DJANGO_SECRET_KEY" >> $DJANGO_PROD_FILE
|
||||
echo "DJANGO_ADMIN_URL=admin/" >> $DJANGO_PROD_FILE
|
||||
echo "USE_DOCKER=yes" >> $DJANGO_PROD_FILE
|
||||
echo "REDIS_URL=redis://redis:6379/0" >> $DJANGO_PROD_FILE
|
||||
echo "CELERY_FLOWER_USER=prod" >> $DJANGO_PROD_FILE
|
||||
echo "CELERY_FLOWER_PASSWORD=$MISTBORN_DEFAULT_PASSWORD" >> $DJANGO_PROD_FILE
|
||||
echo "MISTBORN_DEFAULT_PASSWORD=$MISTBORN_DEFAULT_PASSWORD" >> $DJANGO_PROD_FILE
|
||||
echo "#MAILGUN_API_KEY=" >> $DJANGO_PROD_FILE
|
||||
echo "#MAILGUN_API_URL=" >> $DJANGO_PROD_FILE
|
||||
echo "#SENTRY_DNS=" >> $DJANGO_PROD_FILE
|
||||
|
||||
# generate production .env file for postgresql
|
||||
POSTGRES_PROD_FILE="./.envs/.production/.postgres"
|
||||
POSTGRES_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")
|
||||
echo "POSTGRES_HOST=postgres" > $POSTGRES_PROD_FILE
|
||||
echo "POSTGRES_PORT=5432" >> $POSTGRES_PROD_FILE
|
||||
echo "POSTGRES_DB=mistborn" >> $POSTGRES_PROD_FILE
|
||||
echo "POSTGRES_USER=prod" >> $POSTGRES_PROD_FILE
|
||||
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> $POSTGRES_PROD_FILE
|
||||
|
||||
|
||||
# generate production .env file for pihole
|
||||
PIHOLE_PROD_FILE="./.envs/.production/.pihole"
|
||||
#WEBPASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")
|
||||
WEBPASSWORD="$1"
|
||||
echo "TZ=\"America/New York\"" > $PIHOLE_PROD_FILE
|
||||
echo "WEBPASSWORD=$WEBPASSWORD" >> $PIHOLE_PROD_FILE
|
||||
|
||||
# generate rocketchat .env files
|
||||
ROCKETCHAT_PROD_FILE="./.envs/.production/.rocketchat"
|
||||
#ROCKETCHAT_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")
|
||||
ROCKETCHAT_PASSWORD="$1"
|
||||
echo "ROCKETCHAT_USER=bot" > $ROCKETCHAT_PROD_FILE
|
||||
echo "ROCKETCHAT_ROOM=GENERAL" >> $ROCKETCHAT_PROD_FILE
|
||||
echo "BOT_NAME=bot" >> $ROCKETCHAT_PROD_FILE
|
||||
echo "ROCKETCHAT_PASSWORD=$ROCKETCHAT_PASSWORD" >> $ROCKETCHAT_PROD_FILE
|
||||
|
||||
# generate nextcloud .env files
|
||||
NEXTCLOUD_PROD_FILE="./.envs/.production/.nextcloud"
|
||||
#NEXTCLOUD_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")
|
||||
NEXTCLOUD_PASSWORD="$1"
|
||||
echo "NEXTCLOUD_ADMIN_USER=mistborn" > $NEXTCLOUD_PROD_FILE
|
||||
echo "NEXTCLOUD_ADMIN_PASSWORD=$NEXTCLOUD_PASSWORD" >> $NEXTCLOUD_PROD_FILE
|
||||
echo "NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.mistborn" >> $NEXTCLOUD_PROD_FILE
|
||||
|
||||
# generate onlyoffice .env files
|
||||
ONLYOFFICE_PROD_FILE="./.envs/.production/.onlyoffice"
|
||||
JWT_SECRET="$1"
|
||||
echo "JWT_ENABLED=true" > $ONLYOFFICE_PROD_FILE
|
||||
echo "JWT_SECRET=$JWT_SECRET" >> $ONLYOFFICE_PROD_FILE
|
||||
|
||||
# generate bitwarden .env files
|
||||
BITWARDEN_PROD_FILE="./.envs/.production/.bitwarden"
|
||||
echo "WEBSOCKET_ENABLED=true" > $BITWARDEN_PROD_FILE
|
||||
echo "SIGNUPS_ALLOWED=true" >> $BITWARDEN_PROD_FILE
|
||||
119
scripts/subinstallers/iptables.sh
Executable file
119
scripts/subinstallers/iptables.sh
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
echo "stop iptables wrappers"
|
||||
if [ "$DISTRO" == "ubuntu" ]; then
|
||||
# Disable UFW
|
||||
sudo systemctl stop ufw || true
|
||||
sudo systemctl disable ufw || true
|
||||
fi
|
||||
|
||||
# default interface
|
||||
iface=$(ip -o -4 route show to default | egrep -o 'dev [^ ]*' | awk '{print $2}')
|
||||
|
||||
# real public interface
|
||||
riface=$(ip -o -4 route get 1.1.1.1 | egrep -o 'dev [^ ]*' | awk '{print $2}')
|
||||
|
||||
# resetting iptables
|
||||
sudo iptables -F
|
||||
sudo iptables -t nat -F
|
||||
sudo iptables -X MISTBORN_LOG_DROP 2>/dev/null || true
|
||||
sudo iptables -X MISTBORN_WIREGUARD_INPUT 2>/dev/null || true
|
||||
sudo iptables -X MISTBORN_WIREGUARD_FORWARD 2>/dev/null || true
|
||||
sudo iptables -X MISTBORN_DOCKER_INPUT 2>/dev/null || true
|
||||
|
||||
# iptables: log and drop chain
|
||||
sudo iptables -N MISTBORN_LOG_DROP
|
||||
sudo iptables -A MISTBORN_LOG_DROP -m limit --limit 2/min -j LOG --log-prefix "[IPTables-Dropped]: " --log-level 4
|
||||
sudo iptables -A MISTBORN_LOG_DROP -j DROP
|
||||
|
||||
# wireguard rules chains
|
||||
sudo iptables -N MISTBORN_WIREGUARD_INPUT
|
||||
sudo iptables -N MISTBORN_WIREGUARD_FORWARD
|
||||
|
||||
# iptables
|
||||
echo "Setting iptables rules"
|
||||
sudo iptables -P INPUT ACCEPT
|
||||
sudo iptables -I INPUT -i lo -j ACCEPT
|
||||
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
# if installing over SSH, add SSH rule
|
||||
if [ ! -z "${SSH_CLIENT}" ]; then
|
||||
SSH_SRC=$(echo $SSH_CLIENT | awk '{print $1}')
|
||||
sudo iptables -A INPUT -p tcp -s $SSH_SRC --dport 22 -j ACCEPT
|
||||
fi
|
||||
|
||||
# docker rules
|
||||
sudo iptables -N MISTBORN_DOCKER_INPUT
|
||||
sudo iptables -A MISTBORN_DOCKER_INPUT -i br-+ -j ACCEPT
|
||||
#sudo iptables -A INPUT ! -i $iface -s 172.16.0.0/12 -j ACCEPT
|
||||
|
||||
# last rules
|
||||
sudo iptables -A INPUT -j MISTBORN_DOCKER_INPUT
|
||||
sudo iptables -A INPUT -j MISTBORN_WIREGUARD_INPUT
|
||||
sudo iptables -A INPUT -j MISTBORN_LOG_DROP
|
||||
sudo iptables -A FORWARD -j MISTBORN_WIREGUARD_FORWARD
|
||||
|
||||
sudo iptables -P INPUT DROP
|
||||
sudo iptables -P FORWARD DROP
|
||||
sudo iptables -P OUTPUT ACCEPT
|
||||
|
||||
#if [ "$iface" == "$riface" ]; then
|
||||
sudo iptables -t nat -I POSTROUTING -o $iface -j MASQUERADE
|
||||
#else
|
||||
# sudo iptables -t nat -I POSTROUTING -o $iface -j MASQUERADE
|
||||
# sudo iptables -t nat -I POSTROUTING -o $riface -j MASQUERADE
|
||||
#fi
|
||||
|
||||
# resetting ip6tables rules
|
||||
sudo ip6tables -F
|
||||
sudo ip6tables -t nat -F
|
||||
sudo ip6tables -X MISTBORN_LOG_DROP 2>/dev/null || true
|
||||
|
||||
# ip6tables: log and drop chain
|
||||
sudo ip6tables -N MISTBORN_LOG_DROP
|
||||
sudo ip6tables -A MISTBORN_LOG_DROP -m limit --limit 6/min -j LOG --log-prefix "[IPTables-Dropped]: " --log-level 4
|
||||
sudo ip6tables -A MISTBORN_LOG_DROP -j DROP
|
||||
|
||||
# ip6tables
|
||||
echo "Setting ip6tables rules"
|
||||
sudo ip6tables -P INPUT ACCEPT
|
||||
sudo ip6tables -I INPUT -i lo -j ACCEPT
|
||||
sudo ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
sudo ip6tables -A INPUT -j MISTBORN_LOG_DROP
|
||||
|
||||
sudo ip6tables -P INPUT DROP
|
||||
sudo ip6tables -P FORWARD DROP
|
||||
sudo ip6tables -P OUTPUT ACCEPT
|
||||
|
||||
|
||||
# initial load update package list
|
||||
sudo apt-get update
|
||||
|
||||
# iptables-persistent
|
||||
if [ ! "$(dpkg-query -l iptables-persistent)" ]; then
|
||||
echo "Installing iptables-persistent"
|
||||
|
||||
# answer variables
|
||||
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections
|
||||
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections
|
||||
|
||||
# install
|
||||
sudo apt-get install -y iptables-persistent ipset
|
||||
else
|
||||
echo "Saving iptables rules"
|
||||
sudo bash -c "iptables-save > /etc/iptables/rules.v4"
|
||||
echo "Saving ip6tables rules"
|
||||
sudo bash -c "ip6tables-save > /etc/iptables/rules.v6"
|
||||
fi
|
||||
|
||||
# IP forwarding
|
||||
sudo sed -i 's/.*net.ipv4.ip_forward.*/net.ipv4.ip_forward=1/' /etc/sysctl.conf
|
||||
sudo sysctl -p /etc/sysctl.conf
|
||||
|
||||
# rsyslog to create /var/log/iptables.log
|
||||
sudo cp ./scripts/conf/15-iptables.conf /etc/rsyslog.d/
|
||||
sudo chown root:root /etc/rsyslog.d/15-iptables.conf
|
||||
sudo systemctl restart rsyslog
|
||||
22
scripts/subinstallers/wireguard.sh
Executable file
22
scripts/subinstallers/wireguard.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Wireguard
|
||||
if [ "$DISTRO" == "raspbian" ]; then
|
||||
echo "Adding Wireguard repo keys"
|
||||
sudo apt-get install -y dirmngr
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8B48AD6246925553
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7638D0442B90D010
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC
|
||||
fi
|
||||
|
||||
echo "Installing Wireguard"
|
||||
if [ "$DISTRO" == "ubuntu" ]; then
|
||||
# Ubuntu
|
||||
sudo add-apt-repository -y ppa:wireguard/wireguard
|
||||
elif [ "$DISTRO" == "debian" ] || [ "$DISTRO" == "raspbian" ]; then
|
||||
# Debian
|
||||
sudo bash -c 'echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list'
|
||||
sudo bash -c "printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable"
|
||||
fi
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y openresolv wireguard
|
||||
Reference in New Issue
Block a user