more docker changes
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -42,5 +42,4 @@ api/tacticalrmm/accounts/management/commands/random_data.py
|
||||
versioninfo.go
|
||||
resource.syso
|
||||
htmlcov/
|
||||
docker-compose.override.yml
|
||||
docker-compose.dev.yml
|
||||
@@ -50,26 +50,26 @@ class Command(BaseCommand):
|
||||
def handle(self, *args, **kwargs):
|
||||
self.mesh_settings = CoreSettings.objects.first()
|
||||
|
||||
# set mesh token if not set
|
||||
if not self.mesh_settings.mesh_token and not hasattr(
|
||||
settings, "MESH_TOKEN_KEY"
|
||||
):
|
||||
filepath = "/opt/tactical/tmp/mesh_token"
|
||||
try:
|
||||
# Check for Mesh Username
|
||||
if not self.mesh_settings.mesh_username and settings.MESH_USERNAME:
|
||||
self.mesh_settings.mesh_username = settings.MESH_USERNAME
|
||||
|
||||
try:
|
||||
with open(filepath, "r") as read_file:
|
||||
key = read_file.readlines()
|
||||
# Check for Mesh Site
|
||||
if not self.mesh_settings.mesh_site and settings.MESH_SITE:
|
||||
self.mesh_settings.mesh_site = settings.MESH_SITE
|
||||
|
||||
# Remove key file contents for security reasons
|
||||
with open(filepath, "w") as write_file:
|
||||
write_file.write("")
|
||||
# Check for Mesh Token
|
||||
if not self.mesh_settings.mesh_token and settings.MESH_TOKEN_KEY:
|
||||
self.mesh_settings.mesh_token = settings.MESH_TOKEN_KEY
|
||||
|
||||
# readlines() returns an array. Get first item
|
||||
self.mesh_settings.mesh_token = key[0].rstrip()
|
||||
self.mesh_settings.save()
|
||||
except:
|
||||
self.stdout.write("Mesh Central key wasn't found")
|
||||
return
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(self.websocket_call())
|
||||
self.stdout.write("Initial Mesh Central setup complete")
|
||||
if self.mesh_settings.mesh_token:
|
||||
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."
|
||||
)
|
||||
|
||||
@@ -18,7 +18,10 @@ TZ_CHOICES = [(_, _) for _ in pytz.all_timezones]
|
||||
|
||||
class CoreSettings(BaseAuditModel):
|
||||
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(
|
||||
models.CharField(max_length=255, null=True, blank=True),
|
||||
@@ -69,17 +72,6 @@ class CoreSettings(BaseAuditModel):
|
||||
if not self.pk and CoreSettings.objects.exists():
|
||||
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)
|
||||
|
||||
def __str__(self):
|
||||
@@ -165,39 +157,6 @@ class CoreSettings(BaseAuditModel):
|
||||
except Exception as 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
|
||||
def serialize(core):
|
||||
# serializes the core and returns json
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
MESH_HOST=mesh.example.com
|
||||
MESH_USER=mesh
|
||||
MESH_PASS=meshpass
|
||||
EMAIL_USER=admin@example.com
|
||||
IMAGE_REPO=
|
||||
VERSION=latest
|
||||
|
||||
# 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_PASSWORD=mongopass
|
||||
|
||||
# database settings
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASS=pass
|
||||
POSTGRES_HOST=db
|
||||
POSTGRES_PASS=postgrespass
|
||||
|
||||
APP_HOST=app.example.com
|
||||
API_HOST=api.example.com
|
||||
|
||||
REDIS_HOST=redis
|
||||
|
||||
SALT_HOST=salt
|
||||
SALT_USER=saltapi
|
||||
SALT_PASS=password
|
||||
|
||||
ADMIN_URL=admin
|
||||
DJANGO_SEKRET=secret12341234123412341234
|
||||
DJANGO_DEBUG=False
|
||||
# salt settings
|
||||
SALT_PASS=saltpass
|
||||
@@ -1,5 +1,7 @@
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ENV TACTICAL_DIR /opt/tactical
|
||||
|
||||
RUN apt-get update && \
|
||||
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 - && \
|
||||
|
||||
@@ -5,11 +5,11 @@ set -e
|
||||
: "${SALT_USER:=saltapi}"
|
||||
: "${SALT_USER:=saltpass}"
|
||||
|
||||
# create salt user
|
||||
useradd -M -s /bin/bash -u 1000 "${SALT_USER}"
|
||||
# create sal 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
|
||||
|
||||
|
||||
cherrypy_config="$(cat << EOF
|
||||
module_dirs: ["/opt/tactical/_modules"]
|
||||
timeout: 20
|
||||
|
||||
@@ -4,50 +4,35 @@ 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
|
||||
ENV PATH ${TACTICAL_DIR}/api/env/bin:$PATH
|
||||
|
||||
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
|
||||
|
||||
# install tactical reqs
|
||||
COPY api/tacticalrmm/requirements.txt ${TACTICAL_TMP_DIR}
|
||||
# copy files from repo
|
||||
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 && \
|
||||
apt-get upgrade -y && \
|
||||
apt-get install -y --no-install-recommends wget ca-certificates gcc libc6-dev && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
pip install --upgrade pip && \
|
||||
mkdir -p ${TACTICAL_DIR}/api && \
|
||||
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 -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 && \
|
||||
tar -xzf /tmp/go1.15.linux-amd64.tar.gz -C /tmp
|
||||
|
||||
|
||||
FROM python:3.8-slim
|
||||
|
||||
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}" && \
|
||||
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 && \
|
||||
groupadd -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
|
||||
COPY docker/containers/tactical/entrypoint.sh /
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
set -e
|
||||
|
||||
: "${TRMM_USER:=tactical}"
|
||||
: "${TRMM_PASS:=tactical}"
|
||||
: "${POSTGRES_HOST:=tactical-postgres}"
|
||||
: "${POSTGRES_PORT:=5432}"
|
||||
: "${POSTGRES_USER:=tactical}"
|
||||
@@ -19,8 +21,6 @@ set -e
|
||||
: "${REDIS_HOST:=tactical-redis}"
|
||||
|
||||
|
||||
source ${TACTICAL_DIR}/api/env/bin/activate
|
||||
|
||||
function check_tactical_ready {
|
||||
sleep 15
|
||||
until [ -f "${TACTICAL_READY_FILE}" ]; do
|
||||
@@ -42,7 +42,14 @@ if [ "$1" = 'tactical-init' ]; then
|
||||
sleep 5
|
||||
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
|
||||
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)
|
||||
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)
|
||||
@@ -96,6 +103,7 @@ SALT_PASSWORD = '${SALT_PASS}'
|
||||
SALT_HOST = '${SALT_HOST}'
|
||||
MESH_USERNAME = '${MESH_USER}'
|
||||
MESH_SITE = 'https://${MESH_HOST}'
|
||||
MESH_TOKEN_KEY = '${MESH_TOKEN_KEY}'
|
||||
REDIS_HOST = '${REDIS_HOST}'
|
||||
MESH_WS_URL = 'ws://${MESH_CONTAINER}:443'
|
||||
EOF
|
||||
@@ -103,12 +111,6 @@ EOF
|
||||
|
||||
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
|
||||
python manage.py migrate --no-input
|
||||
python manage.py collectstatic --no-input
|
||||
@@ -117,6 +119,9 @@ EOF
|
||||
python manage.py load_chocos
|
||||
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 -R "${TACTICAL_USER}":"${TACTICAL_USER}" "${TACTICAL_DIR}"
|
||||
|
||||
@@ -130,6 +135,7 @@ if [ "$1" = 'tactical-backend' ]; then
|
||||
check_tactical_ready
|
||||
|
||||
# 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-access.log
|
||||
tail -n 0 -f ${TACTICAL_DIR}/api/tacticalrmm/logs/gunicorn*.log &
|
||||
@@ -147,14 +153,17 @@ if [ "$1" = 'tactical-backend' ]; then
|
||||
fi
|
||||
|
||||
if [ "$1" = 'tactical-celery' ]; then
|
||||
check_tactical_ready
|
||||
test -f "${TACTICAL_DIR}/api/celerybeat.pid" && rm "${TACTICAL_DIR}/api/celerybeat.pid"
|
||||
celery -A tacticalrmm worker
|
||||
fi
|
||||
|
||||
if [ "$1" = 'tactical-beat' ]; then
|
||||
check_tactical_ready
|
||||
celery -A tacticalrmm beat
|
||||
fi
|
||||
|
||||
if [ "$1" = 'tactical-celerywinupdate' ]; then
|
||||
check_tactical_ready
|
||||
celery -A tacticalrmm worker -Q wupdate
|
||||
fi
|
||||
@@ -15,7 +15,6 @@ networks:
|
||||
# docker managed persistent volumes
|
||||
volumes:
|
||||
tactical_data:
|
||||
tactical_certs:
|
||||
salt_data:
|
||||
postgres_data:
|
||||
mongo_data:
|
||||
@@ -51,6 +50,8 @@ services:
|
||||
APP_HOST: ${APP_HOST}
|
||||
API_HOST: ${API_HOST}
|
||||
MESH_HOST: ${MESH_HOST}
|
||||
TRMM_USER: ${TRMM_USER}
|
||||
TRMM_PASS: ${TRMM_PASS}
|
||||
depends_on:
|
||||
- tactical-postgres
|
||||
- tactical-meshcentral
|
||||
@@ -112,7 +113,7 @@ services:
|
||||
networks:
|
||||
- proxy
|
||||
environment:
|
||||
- API_HOST=${API_HOST}
|
||||
API_HOST: ${API_HOST}
|
||||
|
||||
# container for django backend
|
||||
tactical-backend:
|
||||
@@ -132,9 +133,9 @@ services:
|
||||
image: ${IMAGE_REPO}tactical-nginx:${VERSION}
|
||||
restart: always
|
||||
environment:
|
||||
- APP_HOST=${APP_HOST}
|
||||
- API_HOST=${API_HOST}
|
||||
- MESH_HOST=${MESH_HOST}
|
||||
APP_HOST: ${APP_HOST}
|
||||
API_HOST: ${API_HOST}
|
||||
MESH_HOST: ${MESH_HOST}
|
||||
networks:
|
||||
proxy:
|
||||
ipv4_address: 172.20.0.20
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
# tactical tactical-nginx tactical-meshcentral tactical-salt
|
||||
|
||||
DOCKER_IMAGES="tactical-frontend"
|
||||
# tactical-frontend tactical-nginx tactical-salt --no-cache
|
||||
DOCKER_IMAGES="tactical"
|
||||
|
||||
cd ..
|
||||
|
||||
for DOCKER_IMAGE in ${DOCKER_IMAGES}; do
|
||||
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
|
||||
Reference in New Issue
Block a user