Improve installation instructions & flow
This commit is contained in:
parent
b94330b7c5
commit
64a3a1c3ad
5
Pipfile
5
Pipfile
@ -19,13 +19,10 @@ user-agents = "*"
|
|||||||
emoji-country-flag = "*"
|
emoji-country-flag = "*"
|
||||||
rules = "*"
|
rules = "*"
|
||||||
gunicorn = "*"
|
gunicorn = "*"
|
||||||
psycopg2 = "*"
|
psycopg2-binary = "*"
|
||||||
redis = "*"
|
redis = "*"
|
||||||
django-redis-cache = "*"
|
django-redis-cache = "*"
|
||||||
pycountry = "*"
|
pycountry = "*"
|
||||||
|
|
||||||
[requires]
|
|
||||||
python_version = "3.6"
|
|
||||||
|
|
||||||
[pipenv]
|
[pipenv]
|
||||||
allow_prereleases = true
|
allow_prereleases = true
|
||||||
|
66
Pipfile.lock
generated
66
Pipfile.lock
generated
@ -1,12 +1,10 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "c7c9248fad70f86dda59b61f823f0992276c6cb9ee7ead05ae5719077c0c0c1f"
|
"sha256": "2cd3e33ea333a40476d2030b6be66826e93c3a4de67032655061725835c92f09"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {},
|
||||||
"python_version": "3.6"
|
|
||||||
},
|
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"name": "pypi",
|
"name": "pypi",
|
||||||
@ -127,14 +125,6 @@
|
|||||||
],
|
],
|
||||||
"version": "==2.9"
|
"version": "==2.9"
|
||||||
},
|
},
|
||||||
"importlib-metadata": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f",
|
|
||||||
"sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"
|
|
||||||
],
|
|
||||||
"markers": "python_version < '3.8'",
|
|
||||||
"version": "==1.6.0"
|
|
||||||
},
|
|
||||||
"kombu": {
|
"kombu": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76",
|
"sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76",
|
||||||
@ -155,21 +145,38 @@
|
|||||||
],
|
],
|
||||||
"version": "==3.1.0"
|
"version": "==3.1.0"
|
||||||
},
|
},
|
||||||
"psycopg2": {
|
"psycopg2-binary": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:132efc7ee46a763e68a815f4d26223d9c679953cd190f1f218187cb60decf535",
|
"sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac",
|
||||||
"sha256:2327bf42c1744a434ed8ed0bbaa9168cac7ee5a22a9001f6fc85c33b8a4a14b7",
|
"sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a",
|
||||||
"sha256:27c633f2d5db0fc27b51f1b08f410715b59fa3802987aec91aeb8f562724e95c",
|
"sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5",
|
||||||
"sha256:2c0afb40cfb4d53487ee2ebe128649028c9a78d2476d14a67781e45dc287f080",
|
"sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04",
|
||||||
"sha256:2df2bf1b87305bd95eb3ac666ee1f00a9c83d10927b8144e8e39644218f4cf81",
|
"sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1",
|
||||||
"sha256:440a3ea2c955e89321a138eb7582aa1d22fe286c7d65e26a2c5411af0a88ae72",
|
"sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5",
|
||||||
"sha256:6a471d4d2a6f14c97a882e8d3124869bc623f3df6177eefe02994ea41fd45b52",
|
"sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce",
|
||||||
"sha256:6b306dae53ec7f4f67a10942cf8ac85de930ea90e9903e2df4001f69b7833f7e",
|
"sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434",
|
||||||
"sha256:a0984ff49e176062fcdc8a5a2a670c9bb1704a2f69548bce8f8a7bad41c661bf",
|
"sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9",
|
||||||
"sha256:ac5b23d0199c012ad91ed1bbb971b7666da651c6371529b1be8cbe2a7bf3c3a9",
|
"sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057",
|
||||||
"sha256:acf56d564e443e3dea152efe972b1434058244298a94348fc518d6dd6a9fb0bb",
|
"sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98",
|
||||||
"sha256:d3b29d717d39d3580efd760a9a46a7418408acebbb784717c90d708c9ed5f055",
|
"sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522",
|
||||||
"sha256:f7d46240f7a1ae1dd95aab38bd74f7428d46531f69219954266d669da60c0818"
|
"sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505",
|
||||||
|
"sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa",
|
||||||
|
"sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3",
|
||||||
|
"sha256:96d3038f5bd061401996614f65d27a4ecb62d843eb4f48e212e6d129171a721f",
|
||||||
|
"sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4",
|
||||||
|
"sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4",
|
||||||
|
"sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266",
|
||||||
|
"sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66",
|
||||||
|
"sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38",
|
||||||
|
"sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3",
|
||||||
|
"sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389",
|
||||||
|
"sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab",
|
||||||
|
"sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb",
|
||||||
|
"sha256:ccdc6a87f32b491129ada4b87a43b1895cf2c20fdb7f98ad979647506ffc41b6",
|
||||||
|
"sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d",
|
||||||
|
"sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162",
|
||||||
|
"sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e",
|
||||||
|
"sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.8.5"
|
"version": "==2.8.5"
|
||||||
@ -292,13 +299,6 @@
|
|||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==5.0.1"
|
"version": "==5.0.1"
|
||||||
},
|
|
||||||
"zipp": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
|
|
||||||
"sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
|
|
||||||
],
|
|
||||||
"version": "==3.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"develop": {
|
"develop": {
|
||||||
|
38
README.md
38
README.md
@ -93,9 +93,9 @@ To install Shynet using the simplest possible setup, follow these instructions.
|
|||||||
|
|
||||||
2. Have a PostgreSQL server ready to go. This can be on the same machine as the deployment, or elsewhere. You'll just need a username, password, and host. (For info on how to setup a PostgreSQL server on Ubuntu, follow [this guide](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-18-04)).
|
2. Have a PostgreSQL server ready to go. This can be on the same machine as the deployment, or elsewhere. You'll just need a username, password, and host. (For info on how to setup a PostgreSQL server on Ubuntu, follow [this guide](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-18-04)).
|
||||||
|
|
||||||
3. Configure an environment file for Shynet. Be sure to swap out the variables below with the correct values for your setup. (The comments refer to the lines that follow.)
|
3. Configure an environment file for Shynet. (For example, create a file called `.env`.) Be sure to swap out the variables below with the correct values for your setup. (The comments refer to the lines that follow. Note that Docker is weird with quotes, so it tends to be better to omit them from your env file.)
|
||||||
|
|
||||||
```env
|
```
|
||||||
# Database
|
# Database
|
||||||
DB_NAME=<your db name>
|
DB_NAME=<your db name>
|
||||||
DB_USER=<your db user>
|
DB_USER=<your db user>
|
||||||
@ -108,33 +108,41 @@ DJANGO_SECRET_KEY=<your Django secret key; just a random string>
|
|||||||
DEBUG=False
|
DEBUG=False
|
||||||
CELERY_TASK_ALWAYS_EAGER=True
|
CELERY_TASK_ALWAYS_EAGER=True
|
||||||
# For better security, set this to your deployment's domain. Comma separated.
|
# For better security, set this to your deployment's domain. Comma separated.
|
||||||
ALLOWED_HOSTS="*"
|
ALLOWED_HOSTS=*
|
||||||
# Set to True (capitalized) if you want people to be able to sign up for your Shynet instance (not recommended)
|
# Set to True (capitalized) if you want people to be able to sign up for your Shynet instance (not recommended)
|
||||||
SIGNUPS_ENABLED=False
|
SIGNUPS_ENABLED=False
|
||||||
# Change as required
|
# Change as required
|
||||||
TIME_ZONE="America/New_York"
|
TIME_ZONE=America/New_York
|
||||||
# Set to "False" if you will not be serving content over HTTPS
|
# Set to "False" if you will not be serving content over HTTPS
|
||||||
SCRIPT_USE_HTTPS=True
|
SCRIPT_USE_HTTPS=True
|
||||||
|
```
|
||||||
|
|
||||||
# The following settings are OPTIONAL and not necessary for most basic deployments
|
For more advanced deployments, you may consider adding the following settings to your environment file. **The following settings are optional, and not required for simple deployments.**
|
||||||
REDIS_CACHE_LOCATION="redis://redis.default.svc.cluster.local/0"
|
|
||||||
|
```env
|
||||||
|
# Email settings
|
||||||
|
EMAIL_HOST_USER=<your SMTP email user>
|
||||||
|
EMAIL_HOST_PASSWORD=<your SMTP email password>
|
||||||
|
EMAIL_HOST=<your SMTP email hostname>
|
||||||
|
SERVER_EMAIL=Shynet <noreply@shynet.example.com>
|
||||||
|
|
||||||
|
# Redis and queue settings; not necessary for single-instance deployments
|
||||||
|
REDIS_CACHE_LOCATION=redis://redis.default.svc.cluster.local/0
|
||||||
# If set, make sure CELERY_TASK_ALWAYS_EAGER is False
|
# If set, make sure CELERY_TASK_ALWAYS_EAGER is False
|
||||||
CELERY_BROKER_URL="redis://redis.default.svc.cluster.local/1"
|
CELERY_BROKER_URL=redis://redis.default.svc.cluster.local/1
|
||||||
EMAIL_HOST_USER=""
|
|
||||||
EMAIL_HOST_PASSWORD=""
|
|
||||||
EMAIL_HOST=""
|
|
||||||
SERVER_EMAIL="Shynet <noreply@shynet.example.com>"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Setup the Shynet database by running `docker run --env-file=<your env file> milesmcc/shynet:latest python manage.py migrate`.
|
4. Setup the Shynet database by running `docker run --env-file=<your env file> milesmcc/shynet:latest python manage.py migrate`.
|
||||||
|
|
||||||
5. Create your admin account by running `docker run -i --env-file=<your env file> milesmcc/shynet:latest python manage.py createsuperuser`.
|
5. Create your admin account by running `docker run --env-file=<your env file> milesmcc/shynet:latest python manage.py registeradmin <your email>`. The command will print a temporary password that you'll be able to use to log in.
|
||||||
|
|
||||||
6. Launch the Shynet server by running `docker run --env-file=<your env file> milesmcc/shynet:latest`.
|
6. Configure Shynet's hostname (e.g. `shynet.example.com` or `localhost:8000`) by running `docker run --env-file=<your env file> milesmcc/shynet:latest python manage.py hostname "<your hostname>"`. This doesn't affect Shynet's bind port; instead, it determines what hostname to inject into the tracking script. (So you'll want to use the "user-facing" hostname here.)
|
||||||
|
|
||||||
7. With the server still running, visit it in a web browser. Go to `http://<your server's location>/admin` and log in with the credentials you setup in step 5. Click on "Sites", then "example.com". Update the values to match your deployment (the domain will be the domain where you'll _eventually_ host Shynet from, and the display name will be used to whitelabel Shynet throughout the management interface). When you're ready, click "Save".
|
7. Name your Shynet instance by running `docker run --env-file=<your env file> milesmcc/shynet:latest python manage.py whitelabel "<your instance name>"`. This could be something like "My Shynet Server" or "Acme Analytics"—whatever suits you.
|
||||||
|
|
||||||
8. Visit your service's homepage, and verify everything looks right!
|
8. Launch the Shynet server by running `docker run --env-file=<your env file> milesmcc/shynet:latest`. You may need to bind Docker's port 8000 (where Shynet runs) to your local port 8000; this can be done using the flag `-p 8000:8000`.
|
||||||
|
|
||||||
|
9. Visit your service's homepage, and verify everything looks right! You should see a login prompt. Log in with the credentials from step 5. You'll probably be prompted to "confirm your email"—if you haven't set up an email server, the confirmation email will be printed to the console instead.
|
||||||
|
|
||||||
**Next steps:** while out of the scope of this short guide, next steps include setting up Shynet behind a reverse proxy (be it your own [Nginx server](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) or [Cloudflare](https://cloudflare.com)), making it run in the background, and integrating it on your sites. Integration instructions are available on each service's management page.
|
**Next steps:** while out of the scope of this short guide, next steps include setting up Shynet behind a reverse proxy (be it your own [Nginx server](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) or [Cloudflare](https://cloudflare.com)), making it run in the background, and integrating it on your sites. Integration instructions are available on each service's management page.
|
||||||
|
|
||||||
|
0
shynet/core/management/commands/__init__.py
Normal file
0
shynet/core/management/commands/__init__.py
Normal file
27
shynet/core/management/commands/hostname.py
Normal file
27
shynet/core/management/commands/hostname.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
from core.models import User
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
|
import uuid
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Configures the Shynet hostname"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"hostname",
|
||||||
|
type=str,
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
site = Site.objects.get(pk=settings.SITE_ID)
|
||||||
|
site.domain = options.get("hostname")
|
||||||
|
site.save()
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(
|
||||||
|
f"Successfully set the hostname to '{options.get('hostname')}'"
|
||||||
|
)
|
||||||
|
)
|
29
shynet/core/management/commands/registeradmin.py
Normal file
29
shynet/core/management/commands/registeradmin.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
from core.models import User
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
|
import uuid
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Creates an admin user with an auto-generated password"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"email",
|
||||||
|
type=str,
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
email = options.get("email")
|
||||||
|
password = get_random_string()
|
||||||
|
User.objects.create_superuser(
|
||||||
|
str(uuid.uuid4()), email=email, password=password
|
||||||
|
)
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS("Successfully created a Shynet superuser")
|
||||||
|
)
|
||||||
|
self.stdout.write(f"Email address: {email}")
|
||||||
|
self.stdout.write(f"Password: {password}")
|
27
shynet/core/management/commands/whitelabel.py
Normal file
27
shynet/core/management/commands/whitelabel.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
from core.models import User
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
|
import uuid
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Configures a Shynet whitelabel"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"name",
|
||||||
|
type=str,
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
site = Site.objects.get(pk=settings.SITE_ID)
|
||||||
|
site.name = options.get("name")
|
||||||
|
site.save()
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(
|
||||||
|
f"Successfully set the whitelabel to '{options.get('name')}'"
|
||||||
|
)
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user