more docker changes

This commit is contained in:
sadnub
2020-11-17 22:55:13 -05:00
parent bc0fc33966
commit 759b05e137
10 changed files with 85 additions and 131 deletions

1
.gitignore vendored
View File

@@ -42,5 +42,4 @@ api/tacticalrmm/accounts/management/commands/random_data.py
versioninfo.go versioninfo.go
resource.syso resource.syso
htmlcov/ htmlcov/
docker-compose.override.yml
docker-compose.dev.yml docker-compose.dev.yml

View File

@@ -50,26 +50,26 @@ class Command(BaseCommand):
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
self.mesh_settings = CoreSettings.objects.first() self.mesh_settings = CoreSettings.objects.first()
# set mesh token if not set try:
if not self.mesh_settings.mesh_token and not hasattr( # Check for Mesh Username
settings, "MESH_TOKEN_KEY" if not self.mesh_settings.mesh_username and settings.MESH_USERNAME:
): self.mesh_settings.mesh_username = settings.MESH_USERNAME
filepath = "/opt/tactical/tmp/mesh_token"
try: # Check for Mesh Site
with open(filepath, "r") as read_file: if not self.mesh_settings.mesh_site and settings.MESH_SITE:
key = read_file.readlines() self.mesh_settings.mesh_site = settings.MESH_SITE
# Remove key file contents for security reasons # Check for Mesh Token
with open(filepath, "w") as write_file: if not self.mesh_settings.mesh_token and settings.MESH_TOKEN_KEY:
write_file.write("") self.mesh_settings.mesh_token = settings.MESH_TOKEN_KEY
# readlines() returns an array. Get first item except AttributeError:
self.mesh_settings.mesh_token = key[0].rstrip() pass
self.mesh_settings.save()
except:
self.stdout.write("Mesh Central key wasn't found")
return
asyncio.get_event_loop().run_until_complete(self.websocket_call()) if self.mesh_settings.mesh_token:
self.stdout.write("Initial Mesh Central setup complete") asyncio.get_event_loop().run_until_complete(self.websocket_call())
self.stdout.write("Initial Mesh Central setup complete")
else:
self.stdout.write(
"Mesh Setup was skipped being the token wasn't set. Set it up manually."
)

View File

@@ -18,7 +18,10 @@ TZ_CHOICES = [(_, _) for _ in pytz.all_timezones]
class CoreSettings(BaseAuditModel): class CoreSettings(BaseAuditModel):
email_alert_recipients = ArrayField( email_alert_recipients = ArrayField(
models.EmailField(null=True, blank=True), null=True, blank=True, default=list, models.EmailField(null=True, blank=True),
null=True,
blank=True,
default=list,
) )
sms_alert_recipients = ArrayField( sms_alert_recipients = ArrayField(
models.CharField(max_length=255, null=True, blank=True), models.CharField(max_length=255, null=True, blank=True),
@@ -69,17 +72,6 @@ class CoreSettings(BaseAuditModel):
if not self.pk and CoreSettings.objects.exists(): if not self.pk and CoreSettings.objects.exists():
raise ValidationError("There can only be one CoreSettings instance") raise ValidationError("There can only be one CoreSettings instance")
# Only runs on first create
if not self.pk:
mesh_settings = self.get_initial_mesh_settings()
if "mesh_token" in mesh_settings:
self.mesh_token = mesh_settings["mesh_token"]
if "mesh_username" in mesh_settings:
self.mesh_username = mesh_settings["mesh_username"]
if "mesh_site" in mesh_settings:
self.mesh_site = mesh_settings["mesh_site"]
return super(CoreSettings, self).save(*args, **kwargs) return super(CoreSettings, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
@@ -165,39 +157,6 @@ class CoreSettings(BaseAuditModel):
except Exception as e: except Exception as e:
logger.error(f"SMS failed to send: {e}") logger.error(f"SMS failed to send: {e}")
def get_initial_mesh_settings(self):
mesh_settings = {}
# Check for Mesh Username
try:
if settings.MESH_USERNAME:
mesh_settings["mesh_username"] = settings.MESH_USERNAME
else:
raise AttributeError("MESH_USERNAME doesn't exist")
except AttributeError:
pass
# Check for Mesh Site
try:
if settings.MESH_SITE:
mesh_settings["mesh_site"] = settings.MESH_SITE
else:
raise AttributeError("MESH_SITE doesn't exist")
except AttributeError:
pass
# Check for Mesh Token
try:
if settings.MESH_TOKEN_KEY:
mesh_settings["mesh_token"] = settings.MESH_TOKEN_KEY
else:
raise AttributeError("MESH_SITE doesn't exist")
except AttributeError:
pass
return mesh_settings
@staticmethod @staticmethod
def serialize(core): def serialize(core):
# serializes the core and returns json # serializes the core and returns json

View File

@@ -1,24 +1,24 @@
MESH_HOST=mesh.example.com IMAGE_REPO=
MESH_USER=mesh VERSION=latest
MESH_PASS=meshpass
EMAIL_USER=admin@example.com
# tactical credentials (Used to login to dashboard)
TRMM_USER=tactical
TRMM_PASS=tactical
# dns settings
APP_HOST=app.simplermm.com
API_HOST=api.simplermm.com
MESH_HOST=mesh.simplermm.com
# mesh settings
MESH_USER=meshcentral
MESH_PASS=meshcentralpass
MONGODB_USER=mongouser MONGODB_USER=mongouser
MONGODB_PASSWORD=mongopass MONGODB_PASSWORD=mongopass
# database settings
POSTGRES_USER=postgres POSTGRES_USER=postgres
POSTGRES_PASS=pass POSTGRES_PASS=postgrespass
POSTGRES_HOST=db
APP_HOST=app.example.com # salt settings
API_HOST=api.example.com SALT_PASS=saltpass
REDIS_HOST=redis
SALT_HOST=salt
SALT_USER=saltapi
SALT_PASS=password
ADMIN_URL=admin
DJANGO_SEKRET=secret12341234123412341234
DJANGO_DEBUG=False

View File

@@ -1,5 +1,7 @@
FROM ubuntu:20.04 FROM ubuntu:20.04
ENV TACTICAL_DIR /opt/tactical
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y ca-certificates wget gnupg2 tzdata supervisor && \ apt-get install -y ca-certificates wget gnupg2 tzdata supervisor && \
wget -O - https://repo.saltstack.com/py3/ubuntu/20.04/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - && \ wget -O - https://repo.saltstack.com/py3/ubuntu/20.04/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - && \

View File

@@ -5,11 +5,11 @@ set -e
: "${SALT_USER:=saltapi}" : "${SALT_USER:=saltapi}"
: "${SALT_USER:=saltpass}" : "${SALT_USER:=saltpass}"
# create salt user # create sal user
useradd -M -s /bin/bash -u 1000 "${SALT_USER}" groupadd -g 1000 "${SALT_USER}"
useradd -M -d "/opt/tactical" -s /bin/bash -u 1000 -g 1000 "${SALT_USER}"
echo "${SALT_USER}:${SALT_PASS}" | chpasswd echo "${SALT_USER}:${SALT_PASS}" | chpasswd
cherrypy_config="$(cat << EOF cherrypy_config="$(cat << EOF
module_dirs: ["/opt/tactical/_modules"] module_dirs: ["/opt/tactical/_modules"]
timeout: 20 timeout: 20

View File

@@ -4,50 +4,35 @@ ARG DEBIAN_FRONTEND=noninteractive
ARG BUILD_DATE ARG BUILD_DATE
ENV TACTICAL_DIR /opt/tactical ENV TACTICAL_DIR /opt/tactical
ENV TACTICAL_TMP_DIR /tmp/tacticalrmm/ ENV TACTICAL_GO_DIR /usr/local/rmmgo
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
ENV TACTICAL_USER tactical ENV TACTICAL_USER tactical
ENV PATH ${TACTICAL_DIR}/api/env/bin:$PATH
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
# install tactical reqs # copy files from repo
COPY api/tacticalrmm/requirements.txt ${TACTICAL_TMP_DIR} COPY api/tacticalrmm ${TACTICAL_DIR}/api
COPY scripts ${TACTICAL_DIR}/scripts
COPY _modules ${TACTICAL_DIR}/_modules
COPY api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/goversioninfo
# install deps
RUN apt-get update && \ RUN apt-get update && \
apt-get upgrade -y && \ apt-get upgrade -y && \
apt-get install -y --no-install-recommends wget ca-certificates gcc libc6-dev && \ apt-get install -y --no-install-recommends wget ca-certificates gcc libc6-dev && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
pip install --upgrade pip && \ pip install --upgrade pip && \
mkdir -p ${TACTICAL_DIR}/api && \
pip install --no-cache-dir virtualenv && python -m virtualenv ${TACTICAL_DIR}/api/env && \ pip install --no-cache-dir virtualenv && python -m virtualenv ${TACTICAL_DIR}/api/env && \
${TACTICAL_DIR}/api/env/bin/pip install --no-cache-dir setuptools wheel gunicorn && \ ${TACTICAL_DIR}/api/env/bin/pip install --no-cache-dir setuptools wheel gunicorn && \
${TACTICAL_DIR}/api/env/bin/pip install --no-cache-dir -r ${TACTICAL_TMP_DIR}/requirements.txt && \ ${TACTICAL_DIR}/api/env/bin/pip install --no-cache-dir -r ${TACTICAL_DIR}/api/requirements.txt && \
wget https://golang.org/dl/go1.15.linux-amd64.tar.gz -P /tmp && \ wget https://golang.org/dl/go1.15.linux-amd64.tar.gz -P /tmp && \
tar -xzf /tmp/go1.15.linux-amd64.tar.gz -C /tmp mkdir -p ${TACTICAL_GO_DIR}/go && \
tar -xzf /tmp/go1.15.linux-amd64.tar.gz -C ${TACTICAL_GO_DIR}/go && \
rm -f /tmp/go1.15.linux-amd64.tar.gz && \
FROM python:3.8-slim groupadd -g 1000 "${TACTICAL_USER}" && \
ARG DEBIAN_FRONTEND=noninteractive
ARG BUILD_DATE
ENV TACTICAL_DIR /opt/tactical
ENV TACTICAL_TMP_DIR /tmp/tacticalrmm
ENV TACTICAL_GO_DIR /usr/local/rmmgo
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
ENV TACTICAL_USER tactical
# create tactical user
RUN groupadd -g 1000 "${TACTICAL_USER}" && \
useradd -M -d "${TACTICAL_DIR}" -s /bin/bash -u 1000 -g 1000 "${TACTICAL_USER}" useradd -M -d "${TACTICAL_DIR}" -s /bin/bash -u 1000 -g 1000 "${TACTICAL_USER}"
# copy files from repo and 1st build step
COPY api/tacticalrmm ${TACTICAL_DIR}/api
COPY scripts ${TACTICAL_DIR}/scripts
COPY _modules ${TACTICAL_DIR}/_modules
COPY api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/goversioninfo
COPY --from=builder /tmp/go ${TACTICAL_GO_DIR}/go
# docker init # docker init
COPY docker/containers/tactical/entrypoint.sh / COPY docker/containers/tactical/entrypoint.sh /
RUN chmod +x /entrypoint.sh RUN chmod +x /entrypoint.sh

View File

@@ -2,6 +2,8 @@
set -e set -e
: "${TRMM_USER:=tactical}"
: "${TRMM_PASS:=tactical}"
: "${POSTGRES_HOST:=tactical-postgres}" : "${POSTGRES_HOST:=tactical-postgres}"
: "${POSTGRES_PORT:=5432}" : "${POSTGRES_PORT:=5432}"
: "${POSTGRES_USER:=tactical}" : "${POSTGRES_USER:=tactical}"
@@ -19,8 +21,6 @@ set -e
: "${REDIS_HOST:=tactical-redis}" : "${REDIS_HOST:=tactical-redis}"
source ${TACTICAL_DIR}/api/env/bin/activate
function check_tactical_ready { function check_tactical_ready {
sleep 15 sleep 15
until [ -f "${TACTICAL_READY_FILE}" ]; do until [ -f "${TACTICAL_READY_FILE}" ]; do
@@ -42,7 +42,14 @@ if [ "$1" = 'tactical-init' ]; then
sleep 5 sleep 5
done done
# check mesh setup and wait for mesh token
until [ -f "${TACTICAL_DIR}/tmp/mesh_token" ]; do
echo "waiting for mesh token to be generated..."
sleep 10
done
# configure django settings # configure django settings
MESH_TOKEN=$(cat ${TACTICAL_DIR}/tmp/mesh_token)
DJANGO_SEKRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 80 | head -n 1) DJANGO_SEKRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 80 | head -n 1)
SALT_PASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1) SALT_PASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)
ADMINURL=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 70 | head -n 1) ADMINURL=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 70 | head -n 1)
@@ -96,6 +103,7 @@ SALT_PASSWORD = '${SALT_PASS}'
SALT_HOST = '${SALT_HOST}' SALT_HOST = '${SALT_HOST}'
MESH_USERNAME = '${MESH_USER}' MESH_USERNAME = '${MESH_USER}'
MESH_SITE = 'https://${MESH_HOST}' MESH_SITE = 'https://${MESH_HOST}'
MESH_TOKEN_KEY = '${MESH_TOKEN_KEY}'
REDIS_HOST = '${REDIS_HOST}' REDIS_HOST = '${REDIS_HOST}'
MESH_WS_URL = 'ws://${MESH_CONTAINER}:443' MESH_WS_URL = 'ws://${MESH_CONTAINER}:443'
EOF EOF
@@ -103,12 +111,6 @@ EOF
echo "${localvars}" > ${TACTICAL_DIR}/api/tacticalrmm/local_settings.py echo "${localvars}" > ${TACTICAL_DIR}/api/tacticalrmm/local_settings.py
# check mesh setup and wait for mesh token
until [ -f "${TACTICAL_DIR}/tmp/mesh_token" ]; do
echo "waiting for mesh token to be generated..."
sleep 10
done
# run migrations and init scripts # run migrations and init scripts
python manage.py migrate --no-input python manage.py migrate --no-input
python manage.py collectstatic --no-input python manage.py collectstatic --no-input
@@ -117,6 +119,9 @@ EOF
python manage.py load_chocos python manage.py load_chocos
python manage.py load_community_scripts python manage.py load_community_scripts
# create super user
echo "from django.contrib.auth.models import User; User.objects.create_superuser('${TRMM_USER}', 'admin@example.com', '${TRMM_PASS}')" | python manage.py shell
# chown everything to tactical user # chown everything to tactical user
chown -R "${TACTICAL_USER}":"${TACTICAL_USER}" "${TACTICAL_DIR}" chown -R "${TACTICAL_USER}":"${TACTICAL_USER}" "${TACTICAL_DIR}"
@@ -130,6 +135,7 @@ if [ "$1" = 'tactical-backend' ]; then
check_tactical_ready check_tactical_ready
# Prepare log files and start outputting logs to stdout # Prepare log files and start outputting logs to stdout
mkdir -p ${TACTICAL_DIR}/api/tacticalrmm/logs
touch ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn.log touch ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn.log
touch ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn-access.log touch ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn-access.log
tail -n 0 -f ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn*.log & tail -n 0 -f ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn*.log &
@@ -147,14 +153,17 @@ if [ "$1" = 'tactical-backend' ]; then
fi fi
if [ "$1" = 'tactical-celery' ]; then if [ "$1" = 'tactical-celery' ]; then
check_tactical_ready
test -f "${TACTICAL_DIR}/api/celerybeat.pid" && rm "${TACTICAL_DIR}/api/celerybeat.pid" test -f "${TACTICAL_DIR}/api/celerybeat.pid" && rm "${TACTICAL_DIR}/api/celerybeat.pid"
celery -A tacticalrmm worker celery -A tacticalrmm worker
fi fi
if [ "$1" = 'tactical-beat' ]; then if [ "$1" = 'tactical-beat' ]; then
check_tactical_ready
celery -A tacticalrmm beat celery -A tacticalrmm beat
fi fi
if [ "$1" = 'tactical-celerywinupdate' ]; then if [ "$1" = 'tactical-celerywinupdate' ]; then
check_tactical_ready
celery -A tacticalrmm worker -Q wupdate celery -A tacticalrmm worker -Q wupdate
fi fi

View File

@@ -15,7 +15,6 @@ networks:
# docker managed persistent volumes # docker managed persistent volumes
volumes: volumes:
tactical_data: tactical_data:
tactical_certs:
salt_data: salt_data:
postgres_data: postgres_data:
mongo_data: mongo_data:
@@ -51,6 +50,8 @@ services:
APP_HOST: ${APP_HOST} APP_HOST: ${APP_HOST}
API_HOST: ${API_HOST} API_HOST: ${API_HOST}
MESH_HOST: ${MESH_HOST} MESH_HOST: ${MESH_HOST}
TRMM_USER: ${TRMM_USER}
TRMM_PASS: ${TRMM_PASS}
depends_on: depends_on:
- tactical-postgres - tactical-postgres
- tactical-meshcentral - tactical-meshcentral
@@ -112,7 +113,7 @@ services:
networks: networks:
- proxy - proxy
environment: environment:
- API_HOST=${API_HOST} API_HOST: ${API_HOST}
# container for django backend # container for django backend
tactical-backend: tactical-backend:
@@ -132,9 +133,9 @@ services:
image: ${IMAGE_REPO}tactical-nginx:${VERSION} image: ${IMAGE_REPO}tactical-nginx:${VERSION}
restart: always restart: always
environment: environment:
- APP_HOST=${APP_HOST} APP_HOST: ${APP_HOST}
- API_HOST=${API_HOST} API_HOST: ${API_HOST}
- MESH_HOST=${MESH_HOST} MESH_HOST: ${MESH_HOST}
networks: networks:
proxy: proxy:
ipv4_address: 172.20.0.20 ipv4_address: 172.20.0.20

View File

@@ -5,13 +5,12 @@
set -o errexit set -o errexit
set -o pipefail set -o pipefail
# tactical tactical-nginx tactical-meshcentral tactical-salt # tactical-frontend tactical-nginx tactical-salt --no-cache
DOCKER_IMAGES="tactical"
DOCKER_IMAGES="tactical-frontend"
cd .. cd ..
for DOCKER_IMAGE in ${DOCKER_IMAGES}; do for DOCKER_IMAGE in ${DOCKER_IMAGES}; do
echo "Building Tactical Image: ${DOCKER_IMAGE}..." echo "Building Tactical Image: ${DOCKER_IMAGE}..."
docker build --pull --no-cache --build-arg BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" -t "${DOCKER_IMAGE}" -f "docker/containers/${DOCKER_IMAGE}/dockerfile" . docker build --pull --build-arg BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" -t "${DOCKER_IMAGE}" -f "docker/containers/${DOCKER_IMAGE}/dockerfile" .
done done