aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2022-12-04 22:20:03 -0800
committerMike Crute <mike@crute.us>2022-12-04 22:20:03 -0800
commit1b297be993b39c38a29f2d4a512fe8f3a9b3cacf (patch)
tree5309589797fd0a8e75b3e8aec37ac3acd96c12bb
parentd4efff4950b6105f1d62362f8944a24659af4ea7 (diff)
downloaddockerfiles-1b297be993b39c38a29f2d4a512fe8f3a9b3cacf.tar.bz2
dockerfiles-1b297be993b39c38a29f2d4a512fe8f3a9b3cacf.tar.xz
dockerfiles-1b297be993b39c38a29f2d4a512fe8f3a9b3cacf.zip
netbox: upgrade to 3.3.9 and remove patches
This change migrates to using simplevisor which handles Vault credential fetching and renewal. It removes quite a lot of fragile hacks at the Django layer in favor of straightforward environment variable passing.
-rw-r--r--netbox/Dockerfile44
-rw-r--r--netbox/Makefile2
-rw-r--r--netbox/config-patch1.diff26
-rw-r--r--netbox/config-patch2.diff92
-rw-r--r--netbox/configuration.py30
-rw-r--r--netbox/django-driver.py77
-rw-r--r--netbox/django-vault-client.py88
-rwxr-xr-xnetbox/entrypoint.sh22
-rwxr-xr-xnetbox/etc/service/netbox-rq/log/run3
-rwxr-xr-xnetbox/etc/service/netbox-rq/run23
-rwxr-xr-xnetbox/etc/service/uwsgi/log/run3
-rwxr-xr-xnetbox/etc/service/uwsgi/run23
-rw-r--r--netbox/netbox.ini (renamed from netbox/etc/uwsgi/netbox.ini)0
-rw-r--r--netbox/settings-patch.diff11
-rw-r--r--netbox/settings.patch10
-rw-r--r--netbox/simplevisor.json69
16 files changed, 126 insertions, 397 deletions
diff --git a/netbox/Dockerfile b/netbox/Dockerfile
index 022aebf..3b63944 100644
--- a/netbox/Dockerfile
+++ b/netbox/Dockerfile
@@ -3,15 +3,13 @@ LABEL maintainer="Mike Crute <mike@crute.us>"
3 3
4ARG netbox_version 4ARG netbox_version
5 5
6ADD config-patch1.diff /config-patch1.diff 6ADD configuration.py /configuration.py
7ADD config-patch2.diff /config-patch2.diff 7ADD settings.patch /settings.patch
8ADD settings-patch.diff /settings-patch.diff
9 8
10RUN set -euxo pipefail; \ 9RUN set -euxo pipefail; \
11 \ 10 \
12 apk --no-cache add \ 11 apk --no-cache add \
13 build-base \ 12 build-base \
14 dumb-init \
15 jpeg-dev \ 13 jpeg-dev \
16 libffi-dev \ 14 libffi-dev \
17 libxml2-dev \ 15 libxml2-dev \
@@ -19,13 +17,13 @@ RUN set -euxo pipefail; \
19 openssl-dev \ 17 openssl-dev \
20 postgresql-dev \ 18 postgresql-dev \
21 py3-pip \ 19 py3-pip \
20 py3-wheel \
22 python3-dev \ 21 python3-dev \
23 runit \
24 su-exec \
25 uwsgi \ 22 uwsgi \
26 uwsgi-python \ 23 uwsgi-python \
27 zlib-dev \ 24 zlib-dev \
28 ; \ 25 ; \
26 \
29 cd /tmp; \ 27 cd /tmp; \
30 wget "https://github.com/netbox-community/netbox/archive/v${netbox_version}.tar.gz"; \ 28 wget "https://github.com/netbox-community/netbox/archive/v${netbox_version}.tar.gz"; \
31 tar -xvf "v${netbox_version}.tar.gz" -C /opt; \ 29 tar -xvf "v${netbox_version}.tar.gz" -C /opt; \
@@ -33,41 +31,31 @@ RUN set -euxo pipefail; \
33 mv /opt/netbox-${netbox_version}/ /opt/netbox/; \ 31 mv /opt/netbox-${netbox_version}/ /opt/netbox/; \
34 \ 32 \
35 cd /; \ 33 cd /; \
36 cp /opt/netbox/netbox/netbox/configuration.example.py /opt/netbox/netbox/netbox/configuration.py; \ 34 mv /configuration.py /opt/netbox/netbox/netbox/configuration.py; \
37 patch -p1 < /config-patch1.diff; \ 35 patch -p1 < /settings.patch; rm /settings.patch; \
38 rm /config-patch1.diff; \
39 \ 36 \
40 addgroup -S netbox; \ 37 addgroup -S netbox; \
41 adduser -S -G netbox netbox; \ 38 adduser -S -G netbox netbox; \
42 chown -R netbox:netbox /opt/netbox/netbox/media; \ 39 chown -R netbox:netbox /opt/netbox/netbox/media; \
43 \ 40 \
44 cd /opt/netbox; \ 41 cd /opt/netbox; \
45 pip3 install wheel; \
46 pip3 install -r requirements.txt; \ 42 pip3 install -r requirements.txt; \
43 pip3 install django-postgresql-setrole; \
47 \ 44 \
48 python3 netbox/manage.py collectstatic --no-input; \ 45 export NETBOX_SECRET_KEY="testing key for running the build"; \
49 \ 46 export NETBOX_DB_PORT="0"; \
50 cd /; \ 47 export NETBOX_REDIS_TASK_DB="0"; \
51 cp /opt/netbox/netbox/netbox/configuration.example.py /opt/netbox/netbox/netbox/configuration.py; \ 48 export NETBOX_REDIS_CACHE_DB="0"; \
52 patch -p1 < /config-patch2.diff; \
53 rm /config-patch2.diff; \
54 \
55 patch -p1 < /settings-patch.diff; \
56 rm /settings-patch.diff; \
57 \ 49 \
58 mkdir -p /usr/lib/python3.8/site-packages/django/db/backends/postgresqlvault; \ 50 python3 netbox/manage.py collectstatic --no-input; \
59 touch /usr/lib/python3.8/site-packages/django/db/backends/postgresqlvault/__init__.py; \
60 \ 51 \
61 rm -rf /root/.cache; \ 52 rm -rf /root/.cache; \
62 apk --no-cache del --purge \ 53 apk --no-cache del --purge \
63 build-base \ 54 build-base \
64 ; 55 ;
65 56
66ADD django-vault-client.py /usr/lib/python3.8/site-packages/django/contrib/vault_client.py 57ADD netbox.ini /etc/uwsgi/netbox.ini
67ADD django-driver.py /usr/lib/python3.8/site-packages/django/db/backends/postgresqlvault/base.py 58ADD simplevisor.json /simplevisor.json
68ADD etc/ /etc/ 59ADD simplevisor /simplevisor
69ADD entrypoint.sh /entrypoint.sh
70 60
71STOPSIGNAL SIGHUP 61CMD [ "/simplevisor" ]
72ENTRYPOINT [ "/entrypoint.sh" ]
73CMD [ "/usr/bin/dumb-init", "/sbin/runsvdir", "/etc/service" ]
diff --git a/netbox/Makefile b/netbox/Makefile
index 1fb4dad..f572b39 100644
--- a/netbox/Makefile
+++ b/netbox/Makefile
@@ -1,4 +1,4 @@
1VERSION=2.11.9 1VERSION=3.3.9
2IMAGE=docker.crute.me/netbox:$(VERSION) 2IMAGE=docker.crute.me/netbox:$(VERSION)
3LATEST=$(subst :$(VERSION),,$(IMAGE)):latest 3LATEST=$(subst :$(VERSION),,$(IMAGE)):latest
4 4
diff --git a/netbox/config-patch1.diff b/netbox/config-patch1.diff
deleted file mode 100644
index cc5c6d2..0000000
--- a/netbox/config-patch1.diff
+++ /dev/null
@@ -1,26 +0,0 @@
1--- a/opt/netbox/netbox/netbox/configuration.py 2021-07-11 22:24:55.365668931 +0000
2+++ b/opt/netbox/netbox/netbox/configuration.py 2021-07-11 22:25:25.077103585 +0000
3@@ -4,11 +4,13 @@
4 # #
5 #########################
6
7+import urllib3; urllib3.disable_warnings()
8+
9 # This is a list of valid fully-qualified domain names (FQDNs) for the NetBox server. NetBox will not permit write
10 # access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name.
11 #
12 # Example: ALLOWED_HOSTS = ['netbox.example.com', 'netbox.internal.local']
13-ALLOWED_HOSTS = []
14+ALLOWED_HOSTS = ['*']
15
16 # PostgreSQL database configuration. See the Django documentation for a complete list of available parameters:
17 # https://docs.djangoproject.com/en/stable/ref/settings/#databases
18@@ -57,7 +59,7 @@
19 # For optimal security, SECRET_KEY should be at least 50 characters in length and contain a mix of letters, numbers, and
20 # symbols. NetBox will not run without this defined. For more information, see
21 # https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY
22-SECRET_KEY = ''
23+SECRET_KEY = 'dummy setup value will get cleared after setup run'
24
25
26 #########################
diff --git a/netbox/config-patch2.diff b/netbox/config-patch2.diff
deleted file mode 100644
index 69162e4..0000000
--- a/netbox/config-patch2.diff
+++ /dev/null
@@ -1,92 +0,0 @@
1--- a/opt/netbox/netbox/netbox/configuration.py 2021-07-11 22:24:55.365668931 +0000
2+++ b/opt/netbox/netbox/netbox/configuration.py 2021-07-11 22:28:09.665982854 +0000
3@@ -4,21 +4,35 @@
4 # #
5 #########################
6
7+import os
8+from django.contrib.vault_client import SimpleVaultClient
9+
10+
11+def _is_affirmative(value):
12+ value = "" if not value else value
13+ return value.lower() in ["yes", "true", "on", "1"]
14+
15+
16 # This is a list of valid fully-qualified domain names (FQDNs) for the NetBox server. NetBox will not permit write
17 # access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name.
18 #
19 # Example: ALLOWED_HOSTS = ['netbox.example.com', 'netbox.internal.local']
20-ALLOWED_HOSTS = []
21+ALLOWED_HOSTS = ['*']
22
23 # PostgreSQL database configuration. See the Django documentation for a complete list of available parameters:
24 # https://docs.djangoproject.com/en/stable/ref/settings/#databases
25+port = os.getenv("NETBOX_DB_PORT")
26 DATABASE = {
27- 'NAME': 'netbox', # Database name
28- 'USER': '', # PostgreSQL username
29- 'PASSWORD': '', # PostgreSQL password
30- 'HOST': 'localhost', # Database server
31- 'PORT': '', # Database port (leave blank for default)
32- 'CONN_MAX_AGE': 300, # Max database connection age
33+ 'NAME': os.getenv("NETBOX_DB_NAME"),
34+ 'HOST': os.getenv("NETBOX_DB_HOST"),
35+ 'PORT': int(port) if port else "",
36+ 'CONN_MAX_AGE': 300,
37+ "VAULT_SKIP_VERIFY": os.getenv("VAULT_SKIP_VERIFY"),
38+ "VAULT_ADDR": os.getenv("VAULT_ADDR"),
39+ "VAULT_TOKEN": os.getenv("VAULT_TOKEN"),
40+ "VAULT_DB_ROLE_NAME": os.getenv("VAULT_DB_ROLE_NAME"),
41+ "VAULT_ROLE_ID": os.getenv("VAULT_ROLE_ID"),
42+ "VAULT_SECRET_ID": os.getenv("VAULT_SECRET_ID"),
43 }
44
45 # Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate
46@@ -26,26 +40,26 @@
47 # to use two separate database IDs.
48 REDIS = {
49 'tasks': {
50- 'HOST': 'localhost',
51+ 'HOST': os.getenv("NETBOX_REDIS_HOST"),
52 'PORT': 6379,
53 # Comment out `HOST` and `PORT` lines and uncomment the following if using Redis Sentinel
54 # 'SENTINELS': [('mysentinel.redis.example.com', 6379)],
55 # 'SENTINEL_SERVICE': 'netbox',
56 'PASSWORD': '',
57- 'DATABASE': 0,
58+ 'DATABASE': int(os.getenv("NETBOX_REDIS_TASK_DB")),
59 'SSL': False,
60 # Set this to True to skip TLS certificate verification
61 # This can expose the connection to attacks, be careful
62 # 'INSECURE_SKIP_TLS_VERIFY': False,
63 },
64 'caching': {
65- 'HOST': 'localhost',
66+ 'HOST': os.getenv("NETBOX_REDIS_HOST"),
67 'PORT': 6379,
68 # Comment out `HOST` and `PORT` lines and uncomment the following if using Redis Sentinel
69 # 'SENTINELS': [('mysentinel.redis.example.com', 6379)],
70 # 'SENTINEL_SERVICE': 'netbox',
71 'PASSWORD': '',
72- 'DATABASE': 1,
73+ 'DATABASE': int(os.getenv("NETBOX_REDIS_CACHE_DB")),
74 'SSL': False,
75 # Set this to True to skip TLS certificate verification
76 # This can expose the connection to attacks, be careful
77@@ -57,7 +71,14 @@
78 # For optimal security, SECRET_KEY should be at least 50 characters in length and contain a mix of letters, numbers, and
79 # symbols. NetBox will not run without this defined. For more information, see
80 # https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY
81-SECRET_KEY = ''
82+vc = SimpleVaultClient(
83+ os.getenv("VAULT_ADDR"),
84+ os.getenv("VAULT_ROLE_ID"),
85+ os.getenv("VAULT_SECRET_ID"),
86+ ssl_verify=not _is_affirmative(os.getenv("VAULT_SKIP_VERIFY"))
87+)
88+SECRET_KEY = vc.get_kv_secret(os.getenv("NETBOX_VAULT_SECRET_NAME"), "key")
89+del vc
90
91
92 #########################
diff --git a/netbox/configuration.py b/netbox/configuration.py
new file mode 100644
index 0000000..9abd2aa
--- /dev/null
+++ b/netbox/configuration.py
@@ -0,0 +1,30 @@
1import os
2
3ALLOWED_HOSTS = ["*"]
4
5DATABASE = {
6 'NAME': os.getenv("NETBOX_DB_NAME"),
7 'HOST': os.getenv("NETBOX_DB_HOST"),
8 'PORT': int(os.getenv("NETBOX_DB_PORT")),
9 'USER': os.getenv("NETBOX_DB_USERNAME"),
10 'PASSWORD': os.getenv("NETBOX_DB_PASSWORD"),
11 'SET_ROLE': os.getenv("NETBOX_SET_ROLE"),
12 'CONN_MAX_AGE': 300,
13}
14
15REDIS = {
16 'tasks': {
17 'HOST': os.getenv("NETBOX_REDIS_HOST"),
18 'PORT': 6379,
19 'DATABASE': int(os.getenv("NETBOX_REDIS_TASK_DB")),
20 'SSL': False,
21 },
22 'caching': {
23 'HOST': os.getenv("NETBOX_REDIS_HOST"),
24 'PORT': 6379,
25 'DATABASE': int(os.getenv("NETBOX_REDIS_CACHE_DB")),
26 'SSL': False,
27 }
28}
29
30SECRET_KEY = os.getenv("NETBOX_SECRET_KEY")
diff --git a/netbox/django-driver.py b/netbox/django-driver.py
deleted file mode 100644
index 80bfa13..0000000
--- a/netbox/django-driver.py
+++ /dev/null
@@ -1,77 +0,0 @@
1import threading
2from datetime import datetime, timedelta
3
4from django.core.exceptions import ImproperlyConfigured
5from django.contrib.vault_client import SimpleVaultClient, Credential
6from django.db.backends.postgresql.base import DatabaseWrapper as OrigWrapper
7
8
9def _is_affirmative(value):
10 value = "" if not value else value
11 return value.lower() in ["yes", "true", "on", "1"]
12
13
14def _must_get(store, key):
15 value = store.get(key)
16
17 if not value:
18 raise ImproperlyConfigured(
19 f"Database parameter {key} is required but not set.")
20
21 return value
22
23
24class DatabaseWrapper(OrigWrapper):
25
26 def __init__(self, *args, **kwargs):
27 super().__init__(*args, **kwargs)
28 self._vault_cache_lock = threading.Lock()
29 self._vault_cred_cache = Credential.empty()
30
31 def close(self):
32 self._vault_cred_cache = Credential.empty()
33 super().close()
34
35 def close_if_unusable_or_obsolete(self):
36 super().close_if_unusable_or_obsolete()
37
38 if self.connection is None:
39 return
40
41 if not self.is_usable():
42 self.close()
43 return
44
45 with self._vault_cache_lock:
46 if not self._vault_cred_cache.is_valid:
47 self.close()
48
49 # All of this is done under lock
50 def _get_vault_cred(self):
51 print("Getting credentials from vault")
52 params = self.settings_dict
53
54 verify = not _is_affirmative(params.get("VAULT_SKIP_VERIFY"))
55 url = _must_get(params, "VAULT_ADDR")
56 token = params.get("VAULT_TOKEN")
57 db_role_name = _must_get(params, "VAULT_DB_ROLE_NAME")
58 role_id = _must_get(params, "VAULT_ROLE_ID")
59 role_secret = _must_get(params, "VAULT_SECRET_ID")
60
61 client = SimpleVaultClient(url, role_id, role_secret, verify)
62
63 self._vault_cred_cache = client.get_db_credential(db_role_name)
64
65 def get_connection_params(self):
66 conn_params = super().get_connection_params()
67
68 # Do the fetch under lock to prevent multiple threads from piling onto
69 # the vault server
70 with self._vault_cache_lock:
71 if not self._vault_cred_cache.is_valid:
72 self._get_vault_cred()
73
74 conn_params["user"] = self._vault_cred_cache.username
75 conn_params["password"] = self._vault_cred_cache.password
76
77 return conn_params
diff --git a/netbox/django-vault-client.py b/netbox/django-vault-client.py
deleted file mode 100644
index 85b5671..0000000
--- a/netbox/django-vault-client.py
+++ /dev/null
@@ -1,88 +0,0 @@
1import os
2import ssl
3import json
4from urllib import request, parse
5from datetime import datetime, timedelta
6
7
8class Credential:
9
10 def __init__(self, data):
11 self.username = data["data"]["username"]
12 self.password = data["data"]["password"]
13
14 # Leave 2 minutes in case we encounter a failure
15 _duration = timedelta(seconds=data["lease_duration"] - 120)
16 self.expires = datetime.now() + _duration
17
18 @classmethod
19 def empty(cls):
20 return cls({
21 "lease_duration": -1,
22 "data": { "username": "", "password": "" }
23 })
24
25 @property
26 def is_valid(self):
27 return self.expires > datetime.now()
28
29
30
31class SimpleVaultClient:
32
33 def __init__(self, base_url, role_id, role_secret, ssl_verify=True):
34 self.base_url = base_url
35 self.ssl_verify = ssl_verify
36 self.role_id = role_id
37 self.role_secret = role_secret
38
39 env_token = os.getenv("VAULT_TOKEN")
40 if env_token:
41 self._token = env_token
42 self._token_expires = None # Token is assumed to never expire
43 else:
44 self._token = None
45 self._token_expires = datetime.now() + timedelta(seconds=-1)
46
47 def _login_approle(self, role_id, secret):
48 res = self._make_request("auth/approle/login", auth=False, data={
49 "role_id": role_id,
50 "secret_id": secret,
51 })
52
53 self._token = res["auth"]["client_token"]
54 self._token_expires = datetime.now() + \
55 timedelta(seconds=res["auth"]["lease_duration"])
56
57 @property
58 def _token_is_expired(self):
59 return self._token_expires and \
60 self._token_expires < (datetime.now() + timedelta(seconds=120))
61
62 def _auth_as_needed(self):
63 if self._token_is_expired:
64 self._login_approle(self.role_id, self.role_secret)
65
66 def _make_request(self, url, data=None, auth=True):
67 context = ssl._create_unverified_context() \
68 if not self.ssl_verify else None
69
70 data = json.dumps(data).encode("utf-8") if data else None
71 headers = { "X-Vault-Token": self._token } if auth else {}
72
73 url = parse.urljoin(self.base_url, parse.urljoin("/v1/", url))
74 req = request.Request(url, headers=headers, data=data)
75 res = request.urlopen(req, context=context)
76
77 if res.status != 200:
78 raise Exception("Failed to fetch credential from vault")
79
80 return json.load(res)
81
82 def get_kv_secret(self, path, key):
83 self._auth_as_needed()
84 return self._make_request(f"kv/data/{path}")["data"]["data"][key]
85
86 def get_db_credential(self, role):
87 self._auth_as_needed()
88 return Credential(self._make_request(f"database/creds/{role}"))
diff --git a/netbox/entrypoint.sh b/netbox/entrypoint.sh
deleted file mode 100755
index a4f844c..0000000
--- a/netbox/entrypoint.sh
+++ /dev/null
@@ -1,22 +0,0 @@
1#!/bin/sh
2
3set -e
4
5cd "/opt/netbox"
6
7# Apply any database migrations
8/sbin/su-exec netbox python3 netbox/manage.py migrate
9
10# Trace any missing cable paths (not typically needed)
11/sbin/su-exec netbox python3 netbox/manage.py trace_paths --no-input
12
13# Delete any stale content types
14/sbin/su-exec netbox python3 netbox/manage.py remove_stale_contenttypes --no-input
15
16# Delete any expired user sessions
17/sbin/su-exec netbox python3 netbox/manage.py clearsessions
18
19# Clear all cached data
20/sbin/su-exec netbox python3 netbox/manage.py invalidate all
21
22exec "$@"
diff --git a/netbox/etc/service/netbox-rq/log/run b/netbox/etc/service/netbox-rq/log/run
deleted file mode 100755
index 6193824..0000000
--- a/netbox/etc/service/netbox-rq/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
1#!/bin/sh
2
3cat -
diff --git a/netbox/etc/service/netbox-rq/run b/netbox/etc/service/netbox-rq/run
deleted file mode 100755
index aa4b675..0000000
--- a/netbox/etc/service/netbox-rq/run
+++ /dev/null
@@ -1,23 +0,0 @@
1#!/bin/sh
2
3# runsv sends us a TERM but uwsgi will only shutdown cleanly
4# if it receives an INT so we need to translate the signal
5# properly for uwsgi
6trap 'kill -INT $PID' TERM
7
8/sbin/su-exec netbox /usr/bin/python3 /opt/netbox/netbox/manage.py rqworker &
9
10PID=$!
11
12# wait for uwsgi, will get cancelled when runsv TERMs us and
13# the trap will get executed next, unless something goes wrong
14# and uwsgi fails then this wait will run
15wait $PID
16
17# if something went wrong then unregister the trap because it
18# won't have a target
19trap - TERM
20
21# waiting on a dead process will return the return code of the
22# processes original exit
23wait $PID
diff --git a/netbox/etc/service/uwsgi/log/run b/netbox/etc/service/uwsgi/log/run
deleted file mode 100755
index 6193824..0000000
--- a/netbox/etc/service/uwsgi/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
1#!/bin/sh
2
3cat -
diff --git a/netbox/etc/service/uwsgi/run b/netbox/etc/service/uwsgi/run
deleted file mode 100755
index e24ede7..0000000
--- a/netbox/etc/service/uwsgi/run
+++ /dev/null
@@ -1,23 +0,0 @@
1#!/bin/sh
2
3# runsv sends us a TERM but uwsgi will only shutdown cleanly
4# if it receives an INT so we need to translate the signal
5# properly for uwsgi
6trap 'kill -INT $PID' TERM
7
8/usr/sbin/uwsgi --ini /etc/uwsgi/netbox.ini &
9
10PID=$!
11
12# wait for uwsgi, will get cancelled when runsv TERMs us and
13# the trap will get executed next, unless something goes wrong
14# and uwsgi fails then this wait will run
15wait $PID
16
17# if something went wrong then unregister the trap because it
18# won't have a target
19trap - TERM
20
21# waiting on a dead process will return the return code of the
22# processes original exit
23wait $PID
diff --git a/netbox/etc/uwsgi/netbox.ini b/netbox/netbox.ini
index 8431c6f..8431c6f 100644
--- a/netbox/etc/uwsgi/netbox.ini
+++ b/netbox/netbox.ini
diff --git a/netbox/settings-patch.diff b/netbox/settings-patch.diff
deleted file mode 100644
index 78510ad..0000000
--- a/netbox/settings-patch.diff
+++ /dev/null
@@ -1,11 +0,0 @@
1--- /opt/netbox/netbox/netbox/settings.py
2+++ /opt/netbox/netbox/netbox/settings.py
3@@ -147,7 +147,7 @@
4 })
5 else:
6 DATABASE.update({
7- 'ENGINE': 'django.db.backends.postgresql'
8+ 'ENGINE': 'django.db.backends.postgresqlvault'
9 })
10
11 DATABASES = {
diff --git a/netbox/settings.patch b/netbox/settings.patch
new file mode 100644
index 0000000..1141d64
--- /dev/null
+++ b/netbox/settings.patch
@@ -0,0 +1,10 @@
1--- a/opt/netbox/netbox/netbox/settings.py 2022-11-30 13:14:00.000000000 -0800
2+++ b/opt/netbox/netbox/netbox/settings.py 2022-12-04 21:35:52.779482819 -0800
3@@ -302,6 +302,7 @@
4 #
5
6 INSTALLED_APPS = [
7+ 'postgresql_setrole',
8 'django.contrib.admin',
9 'django.contrib.auth',
10 'django.contrib.contenttypes',
diff --git a/netbox/simplevisor.json b/netbox/simplevisor.json
new file mode 100644
index 0000000..666a765
--- /dev/null
+++ b/netbox/simplevisor.json
@@ -0,0 +1,69 @@
1{
2 "env": {
3 "pass": [
4 "PATH",
5 "HOSTNAME",
6 "SHLVL",
7 "HOME",
8 "PWD",
9
10 "NETBOX_REDIS_TASK_DB",
11 "NETBOX_DB_HOST",
12 "NETBOX_DB_PORT",
13 "NETBOX_REDIS_HOST",
14 "NETBOX_DB_NAME",
15 "NETBOX_REDIS_CACHE_DB",
16 "NETBOX_DB_USERNAME",
17 "NETBOX_DB_PASSWORD",
18 "NETBOX_DELETE_LEGACY_DATA",
19 "NETBOX_SET_ROLE",
20 "NETBOX_SECRET_KEY"
21 ],
22 "vault-replace": [
23 "NETBOX_DB_USERNAME",
24 "NETBOX_DB_PASSWORD",
25 "NETBOX_SECRET_KEY"
26 ]
27 },
28 "jobs": {
29 "init": [
30 {
31 "name": "migrate",
32 "cmd": ["/usr/bin/python3", "/opt/netbox/netbox/manage.py", "migrate"],
33 "run-as": "netbox"
34 },
35 {
36 "name": "trace_paths",
37 "cmd": ["/usr/bin/python3", "/opt/netbox/netbox/manage.py", "trace_paths", "--no-input"],
38 "run-as": "netbox"
39 },
40 {
41 "name": "remove_stale_contenttypes",
42 "cmd": ["/usr/bin/python3", "/opt/netbox/netbox/manage.py", "remove_stale_contenttypes", "--no-input"],
43 "run-as": "netbox"
44 },
45 {
46 "name": "clearsessions",
47 "cmd": ["/usr/bin/python3", "/opt/netbox/netbox/manage.py", "clearsessions"],
48 "run-as": "netbox"
49 },
50 {
51 "name": "clearcache",
52 "cmd": ["/usr/bin/python3", "/opt/netbox/netbox/manage.py", "clearcache"],
53 "run-as": "netbox"
54 }
55 ],
56 "main": [
57 {
58 "name": "queue-worker",
59 "cmd": ["/usr/bin/python3", "/opt/netbox/netbox/manage.py", "rqworker"],
60 "run-as": "netbox"
61 },
62 {
63 "cmd": ["/usr/sbin/uwsgi", "--ini", "/etc/uwsgi/netbox.ini"],
64 "kill-signal": "INT",
65 "run-as": "root"
66 }
67 ]
68 }
69}